From nobody Thu Apr 2 01:24:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1774897559; cv=none; d=zohomail.com; s=zohoarc; b=k7gMWwF8Ips2nFkqrQQoMVcTgxm+9fTwA0QFInMm7bogOxPoF8QtMHonZJkvJ6vvD13HxoTnOUGWut5gS8sNMhQdb3liY/KU1TEyAi0dGvrJFGryl2X870Yghasm3WncWNbGNELEL9UVqUQfiO2sPqDWOYGDaiRC+4l/QPwhFE4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774897559; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GWXg+mj1MOof8W2D421QpIVtIcM/Q39yej/+pKha1zc=; b=a70iZdnqZ/86pb93+Uf4y+hvFdIxzanhkJV4/aKNs2/onicGK1H+Jvl4dCdcE/oLVScxqeYRQaqmijrEirMk6REwwt/oL6jDF/9K+q0pwxO8E7l50gREoRe1thHmBkOqCpyzL8Y5ZhQPAXB/w0IalsbXGzPseiCATPj3g5PY45A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774897559974602.8940707655246; Mon, 30 Mar 2026 12:05:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w7Hvi-0003pt-B2; Mon, 30 Mar 2026 15:05:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w7HvV-0003ok-Gl for qemu-devel@nongnu.org; Mon, 30 Mar 2026 15:05:29 -0400 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w7HvS-0005DJ-9W for qemu-devel@nongnu.org; Mon, 30 Mar 2026 15:05:27 -0400 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-82ae378fff8so3067187b3a.2 for ; Mon, 30 Mar 2026 12:05:25 -0700 (PDT) Received: from [127.0.1.1] (191.68.231.218.rev.ocx2915.net. [218.231.68.191]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82ca84644d9sm8496989b3a.13.2026.03.30.12.05.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 12:05:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774897524; x=1775502324; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=GWXg+mj1MOof8W2D421QpIVtIcM/Q39yej/+pKha1zc=; b=NxbyE7GDpfa0A3980XL0Faqc17PU6RzqiqYAagwzVXOhLjY2Eo4DxSPnBd4gYkW/xB Oq3dG/wcLOkuEckkkCTrV0CEWcH5e/xVUGKckmqHBPoR6UkVwttiFNITixRpHtidpcCU 0nNOeCbRPXRfGuEEi5YOVf2LaTU8T6kmN3G/WfAKh6WgKpP8uPQD1b8u2o/I8qd91Q9l +6tG9f5wPYp7pPccKZy1oj8MwnoFD1yU/Kh872J3yyd0m9gSnJEVrw9BSeMEG6cGBTsf RKDyBGYIbxvCi43ERjyXCrsQ92Dq/jGhIS7hf5RfQ5gXEmL/eTOv0UwfJj7pgVEBWiue nCGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774897524; x=1775502324; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=GWXg+mj1MOof8W2D421QpIVtIcM/Q39yej/+pKha1zc=; b=dVLJZmb+02LJvDlo2rx4hIvVo5vzdEAzbHfq9VItHYRnyIO8L6bZEPILqoYo7+tFTW NJpLQUHO+Th3ZRfwVJmbjlkTkR4BfJCEORdeiPFkHlS+2YVXBExlQU5YCualL2HcpBw6 5yv7ILs4O3Grp7LNOZ6Y5y/nCtceLixu5NjxTB5UyV4FhPnsmP829qxOsI8hlKuRreo5 XaDaNa5xGFWi4fY47Mw6+p+8gCQWXng20TOQosv1W0PomZnZwLibJu1DiPahwFiAWdR/ S/jLrIlhoVDqX84Zn1B3BE+N5bWAzr6ceDoxTXP2YHD7M1wnUlqsXb7CRpodsHcAGr0A zwOA== X-Gm-Message-State: AOJu0YwspvY3ANDzojqcRr/zkD9L0a1EHgdKBOIYJns4P3J2ssB85Ene E74Ssj6qs8B5ysLShHEr8suwkBHvMBeA1Ezdd1gSpsgmbEdFuXPrvyMCqDmpiQ== X-Gm-Gg: ATEYQzx1/GQadZJgRtZYldTNYg4+E75Do8LyBFSLSrwp4+WPyIs5peIMDomQd7Sa4+l jWUteeT8Ixo9d/GkvoQAvi3iLlbuSFwMwfLNdW0uKB6R0QO0lDWWizxepCU34ZNkG32YZY388tC hVR7fgyHQo89cXmURGnPVd06vS5NAn/dpd00zTQ6ps3msHaMsV16bxPd5FOQMV3ocYH3Vp6zkrL DzU1hmnKb08Q/3igFDw83U0mBo+e61rbuQItwVFWUCQNP6tGUfTg4qvv/IcFm0K141TXDF+OiO/ pdAUHBFUofqpUbcQijJNFc3K86XSLVTcSlU67/Z2jIInlRlX7Vqcjj1EaXIhvOpOp05VVX2fSvE AIWN0ulGlhvtN+seYzswKgW3w29vFx6vZPrNvvJlFv8iFCFcbgAFR/i7VdK61GiqCrYBHcKzkC7 vsNDnaIRytskGETrhT76FhbDz/j1uTLGh2YBPTLzeH455bHOSV/LJEbgLOrWYCjgMIgtR1XkT/N zLy9bYWcwQxJCemo5sX8DnYA7n9 X-Received: by 2002:a05:6a00:1ca8:b0:82a:778:cd73 with SMTP id d2e1a72fcca58-82c96039a20mr11884762b3a.51.1774897524430; Mon, 30 Mar 2026 12:05:24 -0700 (PDT) From: Takeru Hayasaka Date: Mon, 30 Mar 2026 19:04:41 +0000 Subject: [PATCH 1/3] migration/postcopy: Extract page fault handler callback MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260330-fast-snapshot-refactor-v1-1-22143e70c467@gmail.com> References: <20260330-fast-snapshot-refactor-v1-0-22143e70c467@gmail.com> In-Reply-To: <20260330-fast-snapshot-refactor-v1-0-22143e70c467@gmail.com> To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Takeru Hayasaka X-Mailer: b4 0.15.1 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42b; envelope-from=hayatake396@gmail.com; helo=mail-pf1-x42b.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1774897561820154100 Introduce a PostcopyPageHandler callback type and use it to decouple the userfaultfd fault thread from the postcopy-specific page request logic. This prepares for fast snapshot load, which will supply pages from a local file instead of requesting them over the network. The fault thread now calls mis->page_fault_handler() instead of postcopy_request_page() directly. For postcopy, the handler is set to postcopy_page_fault_handler() which delegates to the existing postcopy_request_page(). No functional change for postcopy migration. Signed-off-by: Takeru Hayasaka --- migration/migration.h | 16 ++++++++++++++++ migration/postcopy-ram.c | 22 +++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/migration/migration.h b/migration/migration.h index b6888daceddf..33525402922d 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -89,6 +89,17 @@ typedef enum { PREEMPT_THREAD_QUIT, } PreemptThreadStatus; =20 +/* + * Callback to handle a page fault from the userfaultfd fault thread. + * Implementations resolve the fault by supplying the requested page, + * e.g., by requesting it from the migration source (postcopy) or by + * reading it from a snapshot file (fast snapshot load). + */ +typedef int (*PostcopyPageHandler)(MigrationIncomingState *mis, + RAMBlock *rb, + ram_addr_t offset, + void *fault_address); + /* State for the incoming migration */ struct MigrationIncomingState { QEMUFile *from_src_file; @@ -116,6 +127,11 @@ struct MigrationIncomingState { QemuThread fault_thread; /* Set this when we want the fault thread to quit */ bool fault_thread_quit; + /* Callback to resolve page faults; set before fault thread starts */ + PostcopyPageHandler page_fault_handler; + void *page_fault_opaque; + /* ptid from current uffd fault msg, for postcopy blocktime tracking */ + uint32_t fault_thread_ptid; =20 bool have_listen_thread; QemuThread listen_thread; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index f5ef93f1933c..8dcd8ff35e85 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -976,6 +976,20 @@ static int postcopy_request_page(MigrationIncomingStat= e *mis, RAMBlock *rb, return migrate_send_rp_req_pages(mis, rb, start, haddr, tid); } =20 +/* + * Default page fault handler for postcopy live migration. + * Requests the faulted page from the source via the return path. + */ +static int postcopy_page_fault_handler(MigrationIncomingState *mis, + RAMBlock *rb, + ram_addr_t offset, + void *fault_address) +{ + return postcopy_request_page(mis, rb, offset, + (uint64_t)(uintptr_t)fault_address, + mis->fault_thread_ptid); +} + /* * Callback from shared fault handlers to ask for a page, * the page must be specified by a RAMBlock and an offset in that rb @@ -1392,9 +1406,9 @@ retry: * Send the request to the source - we want to request one * of our host page sizes (which is >=3D TPS) */ - ret =3D postcopy_request_page(mis, rb, rb_offset, - msg.arg.pagefault.address, - msg.arg.pagefault.feat.ptid); + mis->fault_thread_ptid =3D msg.arg.pagefault.feat.ptid; + ret =3D mis->page_fault_handler(mis, rb, rb_offset, + (void *)(uintptr_t)msg.arg.pagefault.address); if (ret) { /* May be network failure, try to wait for recovery */ postcopy_pause_fault_thread(mis); @@ -1552,6 +1566,8 @@ int postcopy_ram_incoming_setup(MigrationIncomingStat= e *mis) return -1; } =20 + mis->page_fault_handler =3D postcopy_page_fault_handler; + postcopy_thread_create(mis, &mis->fault_thread, MIGRATION_THREAD_DST_FAULT, postcopy_ram_fault_thread, QEMU_THREAD_JOINABLE= ); --=20 2.43.0 From nobody Thu Apr 2 01:24:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1774897603; cv=none; d=zohomail.com; s=zohoarc; b=miYnxocGugAQ+Zi5QMR9PKyyPex9kJBRFGdQbpkh5nqRTcvIKw/pGu8a3UYP4AonJvSQAgnXftiPZw+3Elf7pjGGlvbCscQbW6bsP1t4hc7WhxrZqVMNgTguMbvxuohPlYsxzILIWOwZNX26dFtTOmNeBCNiOIZpQoDqzVCrUeo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774897603; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=xvDeM0TyoHIJuMI9O46gKFM23hqyKFmD6p428QNsoc8=; b=RjO981JQcrSpWVfFFktf4fcd8ZE8S+p3VxXm00jVk5lu1uThdEfjsH7w0dJMLg8gR1kPXnqBNa+RAAENvVCvayJQnbk2vcc42HZeWsCYJxXswTTm6FkqTJQWj2/OKEXeNCFLEQ5vh7jaRgVPLYErJYvjQ6eiSk8b7nA74g80180= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774897603974827.194820610871; Mon, 30 Mar 2026 12:06:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w7HwM-0004IE-8A; Mon, 30 Mar 2026 15:06:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w7HvX-0003pD-En for qemu-devel@nongnu.org; Mon, 30 Mar 2026 15:05:33 -0400 Received: from mail-pf1-x435.google.com ([2607:f8b0:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w7HvV-0005De-88 for qemu-devel@nongnu.org; Mon, 30 Mar 2026 15:05:31 -0400 Received: by mail-pf1-x435.google.com with SMTP id d2e1a72fcca58-82cd5c07f93so124195b3a.1 for ; Mon, 30 Mar 2026 12:05:27 -0700 (PDT) Received: from [127.0.1.1] (191.68.231.218.rev.ocx2915.net. [218.231.68.191]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82ca84644d9sm8496989b3a.13.2026.03.30.12.05.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 12:05:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774897526; x=1775502326; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=xvDeM0TyoHIJuMI9O46gKFM23hqyKFmD6p428QNsoc8=; b=nFjnuKfRiMTEaoXQxV6tSu+jj6WVg9ZKsf3DXrfKHK4nYllSlLlnUM3WvoGWt1E33u EylmwoldGEwfyCoYoIOb6XF6kjzhsHeP4LrblXVFeF+dbvLApXzdxExDDlAtvKw60lcF AbTVrnhvkbu+W6f5L6fWhel2jwvTDuRpUJSpzDyuiApnFsAsUbw8iy/+PQ/3WsDsr6Qt ABTj9pZwAmuSbxnG3iLOkpsQSb5dpQSNGf0fAWf8q5mgohoRC3xoMfiCQoyZ9mRsrNR1 3xWlkfBRsA7fXCGENuJeGG9RVLBGGPocInWMXM+O5NXiLsXKTOR6JwuFN2rYNCQja1QI LiNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774897526; x=1775502326; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=xvDeM0TyoHIJuMI9O46gKFM23hqyKFmD6p428QNsoc8=; b=L5tDshO45ljw04E/NDc0xq3yP2R4SvHRbHz/irWKT+fpJqlhAIJ/XfhskaPOs4qtl1 3O5Cer6165LBJJS6Mr63sPbPBPBipd8jQ/Nl1xhJ828Ar9r50TNAIu5ygZ2V7xv8uR5f agLsshcgtrpr5f+DYGEbmNYlU4ecn2vpoVxGKdQenqusGAPUoCAvE1/kOLZ0pXqeEnK4 nPFeIwh9fgEw5xcguTfT3NRvoCVAju5JCxy5bRMr7waTk308xbWjrb2abDpNoUcJ4H/5 MG8lKwzfGqawRJaHObLiHMrc2RfQMTu8DM6zDOcoNxu2TkQwT78JQ8dbz3uyknbSTHj5 Fi2Q== X-Gm-Message-State: AOJu0YyYpbslQIxx6v+3sN7L7aAYxr4k2/u9MtvD/pZZ+9JNxFZkRcDN UNa+/thdAzBSY4uYlo33E9DWdfqJoqMtbiCRQx9MVhEnsAEBfvaXsQhNw31EFg== X-Gm-Gg: ATEYQzwireBcz/i6SK3Y/5MGw9Ey/pe7Uu72Exz01fzyxw0U8rAwO2PuXSJNYlEAUp3 VQI7hJLi+IPm+Q04YIfIDJxpmKVVgU9Upk1XpdRyy2FjXE8BqdFb50AJ3smz7cNI/wqbhMC6eXh cvEFYPWD6GFpOSpvGl1ry1YIG5e1KS6w++XcV12KToxrB4uWLQZqzAEWL64KSdvXqelOqpW2kBX /K2G7SP0zhDWhFg9RLmLlQXfxNhy4jAdI8aWhVorw/Os4zCUQVD9qshGmah/1BurIJuIrFKPkEB bsJM4Cx302fFgEfrJH/eVQxMOkJ/s2DBsZCXeIWhVsMwyIPI4RBu/kxjn9KmgV1WehMH/qMBL0d NXuuq/qGclM4YBpwIBhiIw2Y0GgJM/XQz06NvwLllk3q9YC4Oe70Sgvrzqjj7BR/T+Y6NME7rGv hCF1lJEEA4F9F6xOVULI7QxX7Fx7HlyZ1xs0CO6noVIr1C0Ehbl3B5D85klkLppAk0SJX0QLa5l IPpIgS1bEW4z9BzCQ== X-Received: by 2002:a05:6a00:1912:b0:7fb:f87d:a0aa with SMTP id d2e1a72fcca58-82c960a60demr12564625b3a.52.1774897526221; Mon, 30 Mar 2026 12:05:26 -0700 (PDT) From: Takeru Hayasaka Date: Mon, 30 Mar 2026 19:04:42 +0000 Subject: [PATCH 2/3] migration/postcopy: Factor out uffd_setup_incoming() from postcopy setup MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260330-fast-snapshot-refactor-v1-2-22143e70c467@gmail.com> References: <20260330-fast-snapshot-refactor-v1-0-22143e70c467@gmail.com> In-Reply-To: <20260330-fast-snapshot-refactor-v1-0-22143e70c467@gmail.com> To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Takeru Hayasaka X-Mailer: b4 0.15.1 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::435; envelope-from=hayatake396@gmail.com; helo=mail-pf1-x435.google.com X-Spam_score_int: -12 X-Spam_score: -1.3 X-Spam_bar: - X-Spam_report: (-1.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URG_BIZ=0.573 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1774897606345154100 Extract the generic userfaultfd initialization from postcopy_ram_incoming_setup() into a new uffd_setup_incoming() function that can be shared between postcopy live migration and fast snapshot load. uffd_setup_incoming() handles: - Opening the userfaultfd and API handshake - Creating the eventfd for quit notification - Setting the page fault handler callback - Starting the fault handler thread - Registering all RAM blocks with UFFDIO_REGISTER - Allocating temporary page buffers for UFFDIO_COPY postcopy_ram_incoming_setup() becomes a thin wrapper that adds postcopy-specific logic: blocktime tracking and the preemption thread. Also move the PostcopyPageHandler typedef from migration.h to postcopy-ram.h where it logically belongs and is needed for the uffd_setup_incoming() declaration. The channels parameter of postcopy_temp_pages_setup() is now passed by the caller instead of being determined internally, so uffd_setup_incoming() callers can control how many temporary page buffers are allocated. No functional change for postcopy migration. Signed-off-by: Takeru Hayasaka --- migration/migration.h | 11 -------- migration/postcopy-ram.c | 66 +++++++++++++++++++++++++++++++++-----------= ---- migration/postcopy-ram.h | 27 ++++++++++++++++++++ 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/migration/migration.h b/migration/migration.h index 33525402922d..43ea32c07ba7 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -89,17 +89,6 @@ typedef enum { PREEMPT_THREAD_QUIT, } PreemptThreadStatus; =20 -/* - * Callback to handle a page fault from the userfaultfd fault thread. - * Implementations resolve the fault by supplying the requested page, - * e.g., by requesting it from the migration source (postcopy) or by - * reading it from a snapshot file (fast snapshot load). - */ -typedef int (*PostcopyPageHandler)(MigrationIncomingState *mis, - RAMBlock *rb, - ram_addr_t offset, - void *fault_address); - /* State for the incoming migration */ struct MigrationIncomingState { QEMUFile *from_src_file; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 8dcd8ff35e85..7af207d6ead5 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -1478,22 +1478,15 @@ retry: return NULL; } =20 -static int postcopy_temp_pages_setup(MigrationIncomingState *mis) +static int postcopy_temp_pages_setup(MigrationIncomingState *mis, + unsigned int channels) { PostcopyTmpPage *tmp_page; int err; - unsigned i, channels; + unsigned i; void *temp_page; =20 - if (migrate_postcopy_preempt()) { - /* If preemption enabled, need extra channel for urgent requests */ - mis->postcopy_channels =3D RAM_CHANNEL_MAX; - } else { - /* Both precopy/postcopy on the same channel */ - mis->postcopy_channels =3D 1; - } - - channels =3D mis->postcopy_channels; + mis->postcopy_channels =3D channels; mis->postcopy_tmp_pages =3D g_new0(PostcopyTmpPage, channels); =20 for (i =3D 0; i < channels; i++) { @@ -1531,7 +1524,19 @@ static int postcopy_temp_pages_setup(MigrationIncomi= ngState *mis) return 0; } =20 -int postcopy_ram_incoming_setup(MigrationIncomingState *mis) +/* + * Generic userfaultfd setup for incoming migration. + * + * Opens the userfaultfd, performs the API handshake, registers all RAM + * blocks for missing-page notifications, allocates temporary page buffers, + * and starts the fault handler thread using the given callback. + * + * Both postcopy live migration and fast snapshot load use this function; + * the caller supplies the appropriate page_fault_handler. + */ +int uffd_setup_incoming(MigrationIncomingState *mis, + PostcopyPageHandler handler, + unsigned int channels) { Error *local_err =3D NULL; =20 @@ -1549,15 +1554,11 @@ int postcopy_ram_incoming_setup(MigrationIncomingSt= ate *mis) */ if (!ufd_check_and_apply(mis->userfault_fd, mis, &local_err)) { error_report_err(local_err); + close(mis->userfault_fd); return -1; } =20 - if (migrate_postcopy_blocktime()) { - assert(mis->blocktime_ctx =3D=3D NULL); - mis->blocktime_ctx =3D blocktime_context_new(); - } - - /* Now an eventfd we use to tell the fault-thread to quit */ + /* An eventfd we use to tell the fault-thread to quit */ mis->userfault_event_fd =3D eventfd(0, EFD_CLOEXEC); if (mis->userfault_event_fd =3D=3D -1) { error_report("%s: Opening userfault_event_fd: %s", __func__, @@ -1566,7 +1567,7 @@ int postcopy_ram_incoming_setup(MigrationIncomingStat= e *mis) return -1; } =20 - mis->page_fault_handler =3D postcopy_page_fault_handler; + mis->page_fault_handler =3D handler; =20 postcopy_thread_create(mis, &mis->fault_thread, MIGRATION_THREAD_DST_FAULT, @@ -1579,11 +1580,29 @@ int postcopy_ram_incoming_setup(MigrationIncomingSt= ate *mis) return -1; } =20 - if (postcopy_temp_pages_setup(mis)) { + if (postcopy_temp_pages_setup(mis, channels)) { /* Error dumped in the sub-function */ return -1; } =20 + return 0; +} + +int postcopy_ram_incoming_setup(MigrationIncomingState *mis) +{ + unsigned int channels; + + if (migrate_postcopy_blocktime()) { + assert(mis->blocktime_ctx =3D=3D NULL); + mis->blocktime_ctx =3D blocktime_context_new(); + } + + channels =3D migrate_postcopy_preempt() ? RAM_CHANNEL_MAX : 1; + + if (uffd_setup_incoming(mis, postcopy_page_fault_handler, channels)) { + return -1; + } + if (migrate_postcopy_preempt()) { /* * This thread needs to be created after the temp pages because @@ -1745,6 +1764,13 @@ int postcopy_request_shared_page(struct PostCopyFD *= pcfd, RAMBlock *rb, g_assert_not_reached(); } =20 +int uffd_setup_incoming(MigrationIncomingState *mis, + PostcopyPageHandler handler, + unsigned int channels) +{ + g_assert_not_reached(); +} + int postcopy_ram_incoming_setup(MigrationIncomingState *mis) { g_assert_not_reached(); diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h index a080dd65a77a..3bbd1ed7e323 100644 --- a/migration/postcopy-ram.h +++ b/migration/postcopy-ram.h @@ -15,10 +15,37 @@ =20 #include "qapi/qapi-types-migration.h" =20 +/* + * Callback to handle a page fault from the userfaultfd fault thread. + * Implementations resolve the fault by supplying the requested page, + * e.g., by requesting it from the migration source (postcopy) or by + * reading it from a snapshot file (fast snapshot load). + */ +typedef int (*PostcopyPageHandler)(MigrationIncomingState *mis, + RAMBlock *rb, + ram_addr_t offset, + void *fault_address); + /* Return true if the host supports everything we need to do postcopy-ram = */ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis, Error **errp); =20 +/* + * Generic userfaultfd setup for incoming migration. + * + * Opens userfaultfd, registers all RAM blocks, allocates temporary + * page buffers and starts the fault handler thread. The caller + * supplies the page_fault_handler callback appropriate for the use + * case (postcopy live migration or fast snapshot load). + * + * @channels: number of temporary page channels to allocate + * (1 for most cases, RAM_CHANNEL_MAX when postcopy preempt + * is enabled). + */ +int uffd_setup_incoming(MigrationIncomingState *mis, + PostcopyPageHandler handler, + unsigned int channels); + /* * Make all of RAM sensitive to accesses to areas that haven't yet been wr= itten * and wire up anything necessary to deal with it. --=20 2.43.0 From nobody Thu Apr 2 01:24:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1774897622; cv=none; d=zohomail.com; s=zohoarc; b=gW3LMM6cO6bBAUfe7KL0A44ixs27UzGATl62ZSAugw2ODoEE91IhrnwTFl4MEcjpdLExrArr/TFWbp5SZKsOJWKINYGPh0jhkckagIxUcP2yEcyhndiQLy+4GF3NxnDn491v9Bw229w5hluoYLgj0fExqBZx9S+AH4qZqRD05yE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774897622; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=2mYxx14F73G5Col0sHTzc8b/F7FosUZb5oC/eLDVHtM=; b=YcwZ/fV+ENgbKtDzigI1lbQvIhmYzPjWQP93s6GZXfHAJxuxHjY/8CHJBgPwxVNipwqstNAm0TnkkgWdqlh7bfWZn3uns+t0iPbc7Z9geDBcNNrBO6zYbflAHLH1GP1Kwk1Syr7abQS2abIv65+1VbrRLv6XeHx17Rl+1hPnPxA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177489762201337.35059492365224; Mon, 30 Mar 2026 12:07:02 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w7HwW-0004cC-Dl; Mon, 30 Mar 2026 15:06:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w7HvY-0003pM-EN for qemu-devel@nongnu.org; Mon, 30 Mar 2026 15:05:34 -0400 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w7HvW-0005Dy-1w for qemu-devel@nongnu.org; Mon, 30 Mar 2026 15:05:32 -0400 Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-82bae83318bso2229487b3a.2 for ; Mon, 30 Mar 2026 12:05:29 -0700 (PDT) Received: from [127.0.1.1] (191.68.231.218.rev.ocx2915.net. [218.231.68.191]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82ca84644d9sm8496989b3a.13.2026.03.30.12.05.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 12:05:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774897528; x=1775502328; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=2mYxx14F73G5Col0sHTzc8b/F7FosUZb5oC/eLDVHtM=; b=kTI0YU1sCj2nTAJ2BINKBVXbIEZa3iw2TnFDRz70pdvdUrz0LWMfAHGdvmQTkdKSaO GtDi6SzfWN3+BMpkqMRbiAvcCdhkkkntq2J0uRyUiL5BIPLXWTsD/pGAy3gsz+NUk0n7 Aa2vdSledGihXrHFsW/j4XtLJ/SfVpYVXzKG0SmQsJnhiQW9TnwRTvXAVH7YKV+JXBbM aa+j4G80EFgnjJXs8IwIpPis+7FtULRefQ7bpfMdfKMuxpu9ya2Un3WW0XOVCv5+ZagP w7zzVpmlAbtUBRLVwQEfh5LvwXmFL3sLAL6yEFHiUfC7TrP+GeQHn1VvdVjQIzTB3lkn Pxag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774897528; x=1775502328; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=2mYxx14F73G5Col0sHTzc8b/F7FosUZb5oC/eLDVHtM=; b=AGson6+7q8oot0rnsh3egaHTVr22/uyk4To7i5efDIy8WD6mA2H/ZrHGokMdJviF62 vn8cdcFjDND81Bu3WGFkoxw4TmSyKfKz4PbzKolwF8IjpU428ao2ych50eRS8bHSAMpU ITY/AVXaNta7M+r+DTbdJKQ+1Q9zj0gr6taYwIIkhUSqDmi51UKFz9H57WCee6bOV7mT BNmf0hVVTiCN9ZtIGEHPZioR31TsGijUcs5fcHR8yWg2fFydSZw7B6Hf4OizBQmMsbAg j49E6zTjQKZbxTStX/kbuAUEwzRE+hBj88uDGnLPb0j4v+29JGX4wwRLdlqmntyuT7/k Ek9w== X-Gm-Message-State: AOJu0YxcUGTXIy4Tw0h3M2E/zC8h7FI6e8B4Kq8OAEIKx8HP/Y/xUlrU AZgjItN0fqco31WAu5ZtWajbD6W1+lwljIV8zG0beVmVe9ChgaQIhxfqI1i9Dw== X-Gm-Gg: ATEYQzwDaKTUPM4+eGQOHpfMjF0UKbKI78G//ZParSoSQ3FvaG6K3pk+rVbqwYaStYj pHu60AyQbVEFVoAI6f6NaSCp0Wmui8bBe/qoYJSQno0Mqly9Mj68x82Emb+GwGZuTi7QVESkKm1 fPUPLcRTQLIB+xNhC+8qyyrOz2QwcWUfgU3S2U7/mcPqARqEleNMkAH6geE897tGmnV2NhjwOCO Yc3r3vx+Pip5S9cfrZ06qNSqdWMjyLT3ic9uH4Mq+kFUBEHUt1NoRSU4EllKvcjnwbcNIdHsFp8 3fLEmNi+tCg+JySC80mScoictXnZuMPYBwp06wplO+63JE3JDjThchp/1OopDQdceEhI3H+U4W/ n3DF8SUmMSxT0tcnGeJtK3ME/njP1QJzBKXIP/GPZGfbPcq56qV53a8PfKw4GzSHJdCpFSNX8p7 EUdEGcBN/iTluvcgMYecA193PX+hOHvQQn17G/iPkDp9mkswiTP7X/OaCiowrrhOcpV9D6bS698 ttTGM/Mch1+9F/kbLvJht5mCmi8 X-Received: by 2002:a05:6a00:8d3:b0:7aa:a2a8:9808 with SMTP id d2e1a72fcca58-82c95e650a6mr13547225b3a.20.1774897528018; Mon, 30 Mar 2026 12:05:28 -0700 (PDT) From: Takeru Hayasaka Date: Mon, 30 Mar 2026 19:04:43 +0000 Subject: [PATCH 3/3] migration/ram: Split mapped-ram header and page loading MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260330-fast-snapshot-refactor-v1-3-22143e70c467@gmail.com> References: <20260330-fast-snapshot-refactor-v1-0-22143e70c467@gmail.com> In-Reply-To: <20260330-fast-snapshot-refactor-v1-0-22143e70c467@gmail.com> To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Takeru Hayasaka X-Mailer: b4 0.15.1 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42d; envelope-from=hayatake396@gmail.com; helo=mail-pf1-x42d.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1774897622630154100 Split parse_ramblock_mapped_ram() into two stages: - parse_ramblock_mapped_ram_header(): reads the MappedRamHeader and dirty bitmap, storing pages_offset and file_bmap on the RAMBlock for later use. - parse_ramblock_mapped_ram_pages(): reads all page data using the bitmap and pages_offset populated by the header stage. The original parse_ramblock_mapped_ram() becomes a thin wrapper that calls both in sequence, preserving the existing behavior. The bitmap is now stored in block->file_bmap (which already exists on RAMBlock for the save side) instead of a function-local variable. The pages function frees the bitmap after loading is complete. This separation prepares for fast snapshot load, which will call only the header stage at load time and defer page loading to a userfaultfd-based demand paging mechanism. No functional change. Signed-off-by: Takeru Hayasaka --- migration/ram.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 979751f61b30..301ef9758e25 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -4152,10 +4152,15 @@ err: return false; } =20 -static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block, - ram_addr_t length, Error **errp) +/* + * Read the mapped-ram header and dirty bitmap for a RAM block. + * + * Populates block->pages_offset and block->file_bmap so that page + * data can be loaded later (either eagerly or on demand). + */ +static void parse_ramblock_mapped_ram_header(QEMUFile *f, RAMBlock *block, + ram_addr_t length, Error **er= rp) { - g_autofree unsigned long *bitmap =3D NULL; MappedRamHeader header; size_t bitmap_size; long num_pages; @@ -4187,19 +4192,54 @@ static void parse_ramblock_mapped_ram(QEMUFile *f, = RAMBlock *block, num_pages =3D length / header.page_size; bitmap_size =3D BITS_TO_LONGS(num_pages) * sizeof(unsigned long); =20 - bitmap =3D g_malloc0(bitmap_size); - if (qemu_get_buffer_at(f, (uint8_t *)bitmap, bitmap_size, + block->file_bmap =3D g_malloc0(bitmap_size); + if (qemu_get_buffer_at(f, (uint8_t *)block->file_bmap, bitmap_size, header.bitmap_offset) !=3D bitmap_size) { error_setg(errp, "Error reading dirty bitmap"); + g_free(block->file_bmap); + block->file_bmap =3D NULL; return; } +} + +/* + * Read all page data for a mapped-ram RAM block using the bitmap + * and pages_offset previously populated by parse_ramblock_mapped_ram_head= er(). + */ +static void parse_ramblock_mapped_ram_pages(QEMUFile *f, RAMBlock *block, + ram_addr_t length, Error **err= p) +{ + long num_pages; =20 - if (!read_ramblock_mapped_ram(f, block, num_pages, bitmap, errp)) { + if (!block->file_bmap) { + /* Shared block that was skipped during header parsing */ return; } =20 + num_pages =3D length / TARGET_PAGE_SIZE; + + if (!read_ramblock_mapped_ram(f, block, num_pages, + block->file_bmap, errp)) { + goto out; + } + /* Skip pages array */ qemu_set_offset(f, block->pages_offset + length, SEEK_SET); + +out: + g_free(block->file_bmap); + block->file_bmap =3D NULL; +} + +static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block, + ram_addr_t length, Error **errp) +{ + parse_ramblock_mapped_ram_header(f, block, length, errp); + if (*errp) { + return; + } + + parse_ramblock_mapped_ram_pages(f, block, length, errp); } =20 static int parse_ramblock(QEMUFile *f, RAMBlock *block, ram_addr_t length) --=20 2.43.0