From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from GVXPR05CU001.outbound.protection.outlook.com (mail-swedencentralazon11023077.outbound.protection.outlook.com [52.101.83.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 03F618015C for ; Wed, 16 Sep 2026 17:18:53 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=b0c1F6SOVj11pHP3OIu+HF5lEDev7Z/ydCpMTwEQK5R0wdywkVAYwVGDDfDHXmFZ60+6w5qu98rP0nMMOVH3fxQ0FP+JolnRE2WIag67t6J7od26R/qXOevEdGjkWhtl8MWZsp1WS7HKZNF6ZTZOcmc9pVtIrmIurx96fWIezgUTxD1MU2DMQG47ks6Rdf+Z+Ot4nnRvUqdNBnOR+8h/1AKDgEEA6+zRYlwEMiz3whH6e4p8APeb0k+oSop9A8t75WNUNEi75Sg1wa6iOfU7DqHSwTEJSgXNtKyVOySRxIjxxgQEeWvqJh9jyZjJbBKolcotyEp8YY8X8QGi4VHOag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=y8u8QkJ/T0dOB3xMFUjvo/LsPKvqyc4G6L8qAKnpd1s=; b=hH/UxyQJsy6tDs8PkkJOHT9eJ3abYxnMQf1J8kyEDNOQyuNWRzDv1pVD6+VYO9NguFNJON4zb9yHR7UA5j/QkmgHuFxFkK0DpMYw3K45brhjaUsjli23FmCOSIMpBPVkngVG99pUdaAfo9MP6ap6yUBV7I/zaw7gLrr1POced16LOJTedK/Zh4eTx6Kxh06mIFQPgmxIKms9k9/YqLgo4KRUGDW3qlAAKRvLOvDLRazeJ1xCGuG19uwzFPiKfk+lBUxZQEGSTnY0nGO9wljLqwbZzHTrgy+f3iDOF+INZg4KiB9XWCUZvPWywZqMPDTZO+L5OjYLQp+koInxOsJezg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=virtuozzo.com; dmarc=pass action=none header.from=virtuozzo.com; dkim=pass header.d=virtuozzo.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=y8u8QkJ/T0dOB3xMFUjvo/LsPKvqyc4G6L8qAKnpd1s=; b=u/UNGaM2ooKHMdiokuMPW6v01hWqk+G0iTyxS1ZhfkMq4BLBXT8RIk2uZykacikYaSdKLlaaznmWfouZsrKXGecZKRmKxCWPItCyhIT5lTJZWsPdOlMtNzQ37O+YMStAV/A3alGsLI9/qu6lavAdJ8N350hidtRoIjKNEoj3Ysas6PEh+WU4u2//kdQgwEpFJ2UKocVnt9ACAAF41p+zJ4V3IyZLEeIO1kio6ShBf3Ad/igfS72KaaMnD3VZ/zchmGjRlOqX/itT0bV5GjUwiR5/4y81UJhjfaM52KjgVwbDv7SA9r0ZO9ihKmidyTFZXzaLsO2I9LX3qh5xPbLkSg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=virtuozzo.com; Received: from VI0PR08MB10656.eurprd08.prod.outlook.com (2603:10a6:800:20a::12) by DBBPR08MB6140.eurprd08.prod.outlook.com (2603:10a6:10:20a::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.11; Wed, 16 Sep 2026 17:18:50 +0000 Received: from VI0PR08MB10656.eurprd08.prod.outlook.com ([fe80::4e37:b189:ddcd:3dd8]) by VI0PR08MB10656.eurprd08.prod.outlook.com ([fe80::4e37:b189:ddcd:3dd8%7]) with mapi id 15.21.0428.008; Wed, 16 Sep 2026 17:18:50 +0000 Message-ID: <901088ac-c450-4eff-8f03-d1a8bca0246a@virtuozzo.com> Date: Wed, 16 Sep 2026 20:18:49 +0300 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH hci-8.0 1/2] migration/cpr: lock the saved fds #VSTOR-145529 To: "Denis V. Lunev" , svt-core@virtuozzo.com References: <20260916143816.1712971-1-den@openvz.org> <20260916143816.1712971-2-den@openvz.org> Content-Language: en-US From: Andrey Drobyshev In-Reply-To: <20260916143816.1712971-2-den@openvz.org> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-ClientProxiedBy: FR3P281CA0164.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:a2::18) To VI0PR08MB10656.eurprd08.prod.outlook.com (2603:10a6:800:20a::12) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI0PR08MB10656:EE_|DBBPR08MB6140:EE_ X-MS-Office365-Filtering-Correlation-Id: b33a68a3-3a92-48d7-788a-08df14169354 List-Id: svt-core@virtuozzo.com X-LD-Processed: 0bc7f26d-0264-416e-a6fc-8352af79c58f,ExtAddr X-MS-Exchange-Transport-Rules-Loop: 1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|23010399003|1800799024|5113699003|18002099003|22082099003|56012099006|5023799004|4143699003|10067099003; X-Microsoft-Antispam-Message-Info: Gr9iNhpbKHKMC0LLgljrP8tZtW+CD/7jcu3+oP0D0xxuw3uyhzkt58+IDIXKCkAwhHa9H58oZkdLRwbPv8tjIrPuu2ElL9NciIFhCVwWZAuBCouyd0EETcZrig8ciznUg6E6HzFjS/dETpK2ByHTXzLxQboxe4ctNWCdHe05QlfHuVhZ7+e2z+4kkFVh02CDg3EQw9aw2RR+mdEMLQLY5GKXwbN+WaGIdlOjVXtDWy9VAZuQwPuFQ7y+7yszZaGVEPijlArLFmGajuSr2JBP7JCM7XyyRzavpM9cN7EfhoGsuomDk1Hwuynd6/Thqmlzn/3GOxhTRvrss6pLMrQEU6WnF8MMO7v53CTa5YnBlKg+CBIUgpZv17IlHHhVp4LE8EJteEpijBRdCby+fBUSUvzTBUCSOcOyrJDLMVz50oyHrW5GWfmOwf55x6B19Fd2crXuzCYza6emmJ4x3KkU3TzaFV2SdRKLhyJxelFWAjf8qxs4B2+kMqMLQXRyLbfc6mZtck7GQLA2L51qKwDIquWwk3cy2tiCFmaCE9YVeIieXJR21FBCDbmujvN88GxUfaO5KtbzRh7tdDxjoTQPqe/XRnPt0/5/8LXaZTQG1AH88BJ+pqeF420yhPlqq8voZ9emIpBLPZqq52tKV8GlGWPWEVcEjiT1APgmGkKKU8w= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI0PR08MB10656.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(376014)(23010399003)(1800799024)(5113699003)(18002099003)(22082099003)(56012099006)(5023799004)(4143699003)(10067099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dzRoeC8rM1BGQXh2S1NNNXZORFFKSWtBVzcyMDc5ZDJxUWFlYk9qVThqTTRu?= =?utf-8?B?N09xR2ZWQmdQcDVqbVFNdzN4ek1RUnlSNzFCdFluaTVCNmtUT3dmTnE1M3Q1?= =?utf-8?B?VEh2anpLbzRLbDN0NlRhRlZqODRyRlJIZ0g3L05WOE1xSU9OWStqZlJPM3Nx?= =?utf-8?B?SnczS0t1RUtaWFZhRGVWdVEyNVcyWm1wdzlMalZpcnk4SVZqR05mQzZJVC84?= =?utf-8?B?NVIwRXBuTTVmZ0JBcVk0My92KzAxcVhodHJ1Q0lNdUFpNXI0cnJnTStlSFov?= =?utf-8?B?YnpmOGowMW9oamROMmVHRFY0UW0xcEpnT2UvQkFJNVdvM1J5Njd3OWhxTTVN?= =?utf-8?B?cmxnU3MzSXo5eTBKblg3cC9NSmF0SUNmRjBsR0xnWExyZ3ZoUjY1elEzUk5x?= =?utf-8?B?ZldtWU1CZm00U3hkN3p0RDZud2o3TkJsd2NicEdwVmtXSWFkb21La3l1VWNV?= =?utf-8?B?d2RMVW5GZ1ErbkN5VU4rK1pYOS8wM2dxUGNEWk5jVVdLS0tpRFdPZmVIL0hY?= =?utf-8?B?bTRnZC9rcGVkL2ZFMStqMkxGRUZiMG1BUXMvK3oyNGdwU1RTcndESDZUYW5M?= =?utf-8?B?a2c3WHJnTmxKd3NpNGt0WU9UN2RsaVZYYkZIU0Z5NWtma0duWG41Mmg5NGw0?= =?utf-8?B?WnA2QkFzK0FoZG5CQlpXYTlZT0FSM3JsNGEwOFB6UEY3NlR3TEpicVg1dEdw?= =?utf-8?B?TU5VeGhCWWVwTmNxZzFJQ3dhRVVERVFBb2xMaUZjRXZXV0JIMDNBNitLakRF?= =?utf-8?B?dFF3djdycng4NWovVGtMbS9WWjNGSU56Mk5iQlQzeGRpR25QQTVhUm9yOWtE?= =?utf-8?B?MEErNlhjR2Fvbk81ZEhSaGkrRWc2SHlJVXV1M3RsSDVocC9TSXNRblB4Tm9x?= =?utf-8?B?OUF4WE1QT0FidTQzSkRDNEdtamd5V2ZOR0UwbHcvNFBVSjE3M2R0Z2FHcmt6?= =?utf-8?B?bnBlQlVRZnlROHBXN0ZLNFUzc2EzbGN3Q2w2cVFkdkNhYndyRVI4dU5INkZm?= =?utf-8?B?OVVvWTdJNmZiY2V1RTJhYTQxUnFXVWx3YVlZS3Yvblg5eEVqVWFMd2Y3ZkM5?= =?utf-8?B?dmdGdWRYYXhCKzdsOWJ1UmphWFFRdVNkWWt4djlaUHkxYlNrTHp4TDlZSGJw?= =?utf-8?B?cjQ5WXV1WU1wQmZuc0dtY0R0QTFXWWpiZk9oYlFBM282bzBYcEduTHVnajJP?= =?utf-8?B?T3JlcDVZaGtTSENqdUpyT2VSMW96Q28rWFBhSEVRUGp2MHhOcEd4WFQrV0Zn?= =?utf-8?B?OVRXbVZHZmdUeVcxYmJ2QW5FaDZNV0VlTjhGc01ZaXZGTEZheXd5VTVQMWox?= =?utf-8?B?b0lsNWl0UzVuTC9oYyt3N01RWkJwUklpNzdqS0ZMVmtWdTlBL2pqNVRHWjVr?= =?utf-8?B?aXIzU0FXNmxRWWNINlRGd1EzdlVYRnlkazFxSlBIL0tmVXdDRFFQSlZkOHFx?= =?utf-8?B?UFMxeHlpMXN2M1FMSlE5bUwxZ3FPT3N4anBzRzJON2F4UGNrMk1IUTBheDBD?= =?utf-8?B?S0JRbzZGcnp3WjJUMXhlbDNDbTRGcWZuOXgxS0h3U3MyVVpKV1hDclA3NW1J?= =?utf-8?B?eTBDaTgzV1p2bE1pVVZ1bGZpbElTL1VuZ3d3YWpwZVNGbUc1Um5SWVJTK3Fh?= =?utf-8?B?TWUvc2h5N1d3RUhvWFRzb080Y0F6N0ZRL1FOR0ZLeDRjTkdlTm5sdE4yYXRV?= =?utf-8?B?b2dvSWIyTUF1dGx1R0lsaFp6b095RXQ1ek8wNnFWUURUdit5Ykl4Lzh5THlO?= =?utf-8?B?WDF4N3c1WkkyaFdSUStGSnNRK2FXRG5RdjNMd1IxdWl6bnJuY2FFZ05GY0hM?= =?utf-8?B?bVgyV2g3Nmw4UjV1MWkxZWNXQzV1RENHTEo2NzJ5QzVLOG8vYmhNT0hjK2N4?= =?utf-8?B?elA2UGJpelVyc2JCQzhuaHdvVzJDYk9PMG4xZDFmUFJIQ1NFTXZJMm96ZVFp?= =?utf-8?B?c1BPcmZMTnk3Zi9ZSzB3Z3NIZ2pXMGNjQWFvdy9sTzV6NG5wUi9Vczlna1pt?= =?utf-8?B?Rmhvd2g4aGYyWnJvd21ERk9wTXpTakdKU0M5T1dYbnYxZWxSd3YvTHZ5NVZ4?= =?utf-8?B?OEdJNnBMcU1jV3grT3pXaXdmVkNqRDhuanlyV1dsZTVBc2plM2o0aEU1eTEw?= =?utf-8?B?cEpoTkE4Tm1sNk10VmpQZ1NWNm5VL2VYQlgzeW42R2JycUFMSVFkaWdGM0tG?= =?utf-8?B?cE8wRjlGRHdtZFhNWXB4UkMyNUVjYVU2aDNDZ1BxTHdzcVpPdXRFTVA4SzF1?= =?utf-8?B?ZXdXWlVGeHdmZjRKZmxnMUc0Y29qRjFBYm9XMW92YkFScS8wNjd0amwyVG1I?= =?utf-8?B?dm9MVWtBekpuSTNWNGJ5ekY0SXZTTEphYStramRWYVA5bjVydzl0UWdndGpG?= =?utf-8?Q?1mOrvngK32aWdiiw=3D?= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-Network-Message-Id: b33a68a3-3a92-48d7-788a-08df14169354 X-MS-Exchange-CrossTenant-AuthSource: VI0PR08MB10656.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Sep 2026 17:18:50.5706 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 4BkbBglCu6B+96bJgBVshwZoXoJmQDPPalVo3iUxwxXUgZoQHH4Ndg0CCMMgfDDb1nlsuZSGcWoQ49UEahG8W2X6lV2OyG72TkVoy6dlJ7M= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB6140 1. Major: lock ordering is created but nowhere documented. This patch already establishes two orders: ram_list.mutex → cpr_state_lock via qemu_ram_free() calling cpr_delete_fd() at system/physmem.c:2409, and chr_write_lock → cpr_state_lock via tcp_chr_disconnect_locked() → tcp_chr_free_connection() at chardev/char-socket.c:361. The ramlist order is only mentioned in patch 2, and the chardev order is not mentioned at all. Put a comment at the lock definition stating it is a leaf lock and listing what may be held on entry. 2. Minor: error_report() under the lock inverts the chardev order. qemu_file_put_fd() calls error_report_err() on failure while cpr_state_save() holds the lock. From an HMP migrate, error_vprintf() routes to monitor_vprintf(), which takes the monitor chardev's chr_write_lock. That is the reverse of order in point 1. No deadlock today since HMP chardevs live on the main thread, but it is exactly the kind of remote breakage the commit message argues against. The error_report() calls in cpr_save_fd() and cpr_save_ramblock() abort right after, so they are moot. Either note the rule in the comment or move error reporting out of the guarded region. 3. Minor: the commit message overstates what stays outside the lock. vmstate_save_state() and vmstate_load_state() run under the lock and read or populate vfio_devices and hotplug_cpus. cpr_cpu_hotplug_needed() fills hotplug_cpus under the lock, while cpr_load_cpu_hotplug_state() and cpr_free_cpu_hotplug_state() walk and free it unlocked from vl.c. Both lists are BQL-only in practice. Document per list in include/migration/cpr.h next to CprState which ones the mutex covers. 4. Minor: cpr_open_fd() holds the mutex across qemu_open(). A blocking open of /dev/vfio/N or /dev/iommu stalls every other accessor, including an iothread chardev disconnect. The fdset path also adds cpr_state_lock → mon_fdsets_lock. The atomic find-then-save is a real improvement over upstream's two separate calls, so keeping it is defensible, but say so in the commit message and add the ordering to the comment. 5. Nit: check-then-act across two acquisitions remains. Callers such as tcp_chr_free_connection() do cpr_find_fd() == fd then cpr_delete_fd(). The lock protects the list, not the returned fd, and another thread can replace the entry between the two calls. Harmless for the existing callers. A cpr_delete_fd_if(name, id, fd) helper would make the pattern atomic. Optional. On 9/16/26 5:38 PM, Denis V. Lunev wrote: > From: Denis V. Lunev > > The cpr state is a process wide registry of the resources that have to > survive an exec. Entries are added and dropped from realize and teardown > paths all over the tree, and a caller has no way to tell which thread the > next caller will run in. > > The state carries no serialization of its own. It is safe today only > because its callers happen to hold the BQL, and that is a property of > where those callers live rather than anything the interface promises or > checks. A caller that is correct within its own subsystem can therefore > break this one from a distance: two that overlap corrupt the registry, > and the next lookup walks an entry that has already been freed. > > Give the state a lock of its own instead of relying on that. Entries > move when a device is realized, when a resource is handed over, and when > a migration starts, so none of this is on a hot path and an uncontended > mutex costs nothing. > > Take the lock in every fd accessor and across the save and load walks. > Holding it over the walk callbacks is safe because none of them comes > back through this interface. State that is not reached through these > accessors, such as the VFIO device list that hw/vfio manipulates > directly, stays outside it. > > Signed-off-by: Denis V. Lunev > --- > migration/cpr.c | 60 ++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 50 insertions(+), 10 deletions(-) > > diff --git a/migration/cpr.c b/migration/cpr.c > index f218e6a66d6..78cf430e386 100644 > --- a/migration/cpr.c > +++ b/migration/cpr.c > @@ -9,6 +9,7 @@ > #include "qemu/error-report.h" > #include "qapi/error.h" > #include "qemu/error-report.h" > +#include "qemu/lockable.h" > #include "hw/vfio/vfio-device.h" > #include "migration/cpr.h" > #include "migration/misc.h" > @@ -33,6 +34,14 @@ > > CprState cpr_state; > > +/* Callers are spread across the tree and need not share a thread. */ > +static QemuMutex cpr_state_lock; > + > +static void __attribute__((constructor)) cpr_state_lock_init(void) > +{ > + qemu_mutex_init(&cpr_state_lock); > +} > + > /****************************************************************************/ > > typedef struct CprFd { > @@ -107,10 +116,22 @@ static CprFd *find_fd(CprFdList *head, const char *name, int id) > return NULL; > } > > -void cpr_delete_fd(const char *name, int id) > +static int do_cpr_find_fd(const char *name, int id) > { > CprFd *elem = find_fd(&cpr_state.fds, name, id); > - int fd = elem ? elem->fd : -1; > + > + return elem ? elem->fd : -1; > +} > + > +void cpr_delete_fd(const char *name, int id) > +{ > + CprFd *elem; > + int fd; > + > + QEMU_LOCK_GUARD(&cpr_state_lock); > + > + elem = find_fd(&cpr_state.fds, name, id); > + fd = elem ? elem->fd : -1; > > if (elem) { > QLIST_REMOVE(elem, next); > @@ -125,6 +146,8 @@ void cpr_delete_fd_all(const char *name) > { > CprFd *elem, *next_elem; > > + QEMU_LOCK_GUARD(&cpr_state_lock); > + > QLIST_FOREACH_SAFE(elem, &cpr_state.fds, next, next_elem) { > if (!strcmp(elem->name, name)) { > QLIST_REMOVE(elem, next); > @@ -136,18 +159,22 @@ void cpr_delete_fd_all(const char *name) > > int cpr_find_fd(const char *name, int id) > { > - CprFd *elem = find_fd(&cpr_state.fds, name, id); > - int fd = elem ? elem->fd : -1; > + int fd; > + > + QEMU_LOCK_GUARD(&cpr_state_lock); > > + fd = do_cpr_find_fd(name, id); > trace_cpr_find_fd(name, id, fd); > return fd; > } > > void cpr_save_fd(const char *name, int id, int fd) > { > - CprFd *elem = find_fd(&cpr_state.fds, name, id); > - int old_fd = elem ? elem->fd : -1; > + int old_fd; > + > + QEMU_LOCK_GUARD(&cpr_state_lock); > > + old_fd = do_cpr_find_fd(name, id); > if (old_fd < 0) { > do_cpr_save_fd(name, id, fd); > } else if (old_fd != fd) { > @@ -161,12 +188,17 @@ void cpr_save_fd(const char *name, int id, int fd) > int cpr_open_fd(const char *path, int flags, const char *name, int id, > Error **errp) > { > - int fd = cpr_find_fd(name, id); > + int fd; > + > + QEMU_LOCK_GUARD(&cpr_state_lock); > + > + fd = do_cpr_find_fd(name, id); > + trace_cpr_find_fd(name, id, fd); > > if (fd < 0) { > fd = qemu_open(path, flags, errp); > if (fd >= 0) { > - cpr_save_fd(name, id, fd); > + do_cpr_save_fd(name, id, fd); > } > } > return fd; > @@ -176,6 +208,8 @@ bool cpr_walk_fd(cpr_walk_fd_cb cb) > { > CprFd *elem; > > + QEMU_LOCK_GUARD(&cpr_state_lock); > + > QLIST_FOREACH(elem, &cpr_state.fds, next) { > g_assert(elem->fd >= 0); > if (!cb(elem->fd)) { > @@ -527,7 +561,9 @@ bool cpr_state_save(MigrationChannel *channel, Error **errp) > qemu_put_be32(f, QEMU_CPR_FILE_MAGIC); > qemu_put_be32(f, QEMU_CPR_FILE_VERSION); > > - ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0, errp); > + WITH_QEMU_LOCK_GUARD(&cpr_state_lock) { > + ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0, errp); > + } > if (ret) { > qemu_fclose(f); > return false; > @@ -561,6 +597,8 @@ static void cpr_prune_closed_fds(void) > { > CprFd *elem, *next; > > + QEMU_LOCK_GUARD(&cpr_state_lock); > + > QLIST_FOREACH_SAFE(elem, &cpr_state.fds, next, next) { > if (fcntl(elem->fd, F_GETFD) < 0 && errno == EBADF) { > trace_cpr_prune_closed_fd(elem->name, elem->id, elem->fd); > @@ -611,7 +649,9 @@ int cpr_state_load(MigrationChannel *channel, Error **errp) > return -ENOTSUP; > } > > - ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1, errp); > + WITH_QEMU_LOCK_GUARD(&cpr_state_lock) { > + ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1, errp); > + } > if (ret) { > qemu_fclose(f); > return ret;