From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qk1-f177.google.com (mail-qk1-f177.google.com [209.85.222.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D587F39A063 for ; Wed, 3 Jun 2026 15:44:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501458; cv=none; b=lSIfi8qA8lpMBZHNsFE+tcL3QRF8sXzudsHcdlWRbacarH1khaBMM9TfDXLBQihvAIYzfeOjp4EEiSWYDWO8VITMbt4ytd0Yj+sgWRKo0yq7tPvLZSgqhYNUmksP7qqMVwbM4qObO/TdvATbGmTV+G7unHGZPYWUfrysybxJXBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501458; c=relaxed/simple; bh=IMbuGTukyT8IG40YTi+316UrswHf2CnDFbSS3RnRmnE=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bQhgLiMFgqgk5/a0XsorZjL+4FKqYI4xpE7IM+ojShnmXiquML5UNSeAp7LiItN1t4UoAOhG2oEtUHpWApGwvSYrjx2QR6NW6KNTvUBjMnuP5Z3Duo0YG02gZwp3UyapTSINztE8uOe7gFZt/rxs0uX9pEAe2Luone5tfYO1i8U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=DdNbKUsI; arc=none smtp.client-ip=209.85.222.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="DdNbKUsI" Received: by mail-qk1-f177.google.com with SMTP id af79cd13be357-91550f68089so418975385a.2 for ; Wed, 03 Jun 2026 08:44:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501456; x=1781106256; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=yVlCXZe8SHDSOJUkKVBaYBikNvs5G4Pkl6SfmcOaAr0=; b=DdNbKUsIU5cZRabA2KkMfpHsJx9+gbaLDAO2hsFZTQLwT+dPPU50h1GalJSF0s6SDJ vgsUSLpdZ6P62da6JT+InKSSvkZzRZ4qQiDXuEKqazYyR63P0GV/ju7Ghz08/QnOUgn4 bLlPGJ6S2ptv4MvgK7ZMC9aSA2aIJ9quqSZtEce1SupHyqHVdYRRQ/PrX5uCavtGKAZw uWHU53+LUXvUqntaw/aMI6AIptwGBZn4cIz7LLJmminRZWNp09HWlJyNbEPExt4opphg 64OQOoCwQ4I+YN4yhoMiu8wG5AqAFUL45z0htUs5iLXW37xRBLHMn4RHSSpGPdcLtk7i aPug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501456; x=1781106256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=yVlCXZe8SHDSOJUkKVBaYBikNvs5G4Pkl6SfmcOaAr0=; b=B0dwdwpscZ3QVoch8SajGb+R9/OnYhEXo66dGQXGUJQ978/0G4YUTRAoOmvWI160YH gLufONW1t55+VPjdS0n+04+/aa15O1wUnOhi5phnhwlvB5WEyd2LYpWTMvHrPB0UAgK3 ZH2/2O90JO+xvKZV7SVNqJJ4S7VF9maP2t/DkPRkFqdQpW91UV0xgFxtpbOfSsm4PrK8 A3KWYKEB6+B9BvO+dg/VHOq3ZheQi0GNlhk6Xgm870zBoJZgMbj2ahNw3kD7mddBl4sq GluYmQDmHniZBMwSXAa7/QSlHe64NG9pO4IunAbhxlKDTOwjU0trjA2c44CwH9W0ZWt+ 3ogQ== X-Forwarded-Encrypted: i=1; AFNElJ/KSLbVpscKPjUUf+QIxBI+FQW6fSoHUjPKSHbBWlTPycOcGkBTr73Y706LzaVBgdYm0/uGIGBdzaqL/Vo=@vger.kernel.org X-Gm-Message-State: AOJu0Yz1FiZaemFrYLyAfGWFnZrJGXvlOKVVJjvke0sajhRq5lNyeV4h bipmXBj3TcDQQXOT/syF6BUcQ+kPWCqxFOPoAOkVmrozUFE828waRX/whWUpRLp6yrQ= X-Gm-Gg: Acq92OG690m0i8IigLsYYYz6p2xPeW3E++9BXHMrueVg0ljZfTZUW6CWpkRBrH4tM5l uBDpEsXjgP2H34R0tkfYnyZzCfkK0yqzNj1FUCl4Glb1cFagq14vOw9zcr7UsNFh9mzFRpJAi1+ hg7yrBDI/6n4hyiZ/gyGBeUsqESeXUEC41AIaGGkIAz3ay2o5jOAjTpZ9R2PRjMHPby3Q8tfxXM ggkx0WN/OR7buOs8hdGJCfabZGkYU809ibdBWqYYwLs8qzrnU/QKo8NLMYwco2Z0yl9qPi0+Iwp N4qPuY6FQrdI7vrUyhZkPd7c3XgOVWnXhjuaPiEzihDjYZFA/3Qf0u6Gu/0rTFQwa56hvHnw9fi 194/2wKAS6UzYJJQiNcMun0ILjJrWRJcUZyn8b+r1BIJQm2Eyrry7ZjkP93wicGG2Zg+/h1iC4B EHoPlMAkRd4slsOJSFs8SG7/I59C1iKC3W8BRm2jqX2SqVEQSIllMXJyGYVANmEg== X-Received: by 2002:a05:620a:2890:b0:915:6cab:768e with SMTP id af79cd13be357-9158a849a62mr658252485a.60.1780501455872; Wed, 03 Jun 2026 08:44:15 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a40d566sm266574585a.47.2026.06.03.08.44.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:44:15 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 01/13] liveupdate: change file_set->count type to u64 for type safety Date: Wed, 3 Jun 2026 15:43:50 +0000 Message-ID: <20260603154402.468928-2-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This improves type safety and aligns the in-memory file_set->count with the serialized count type. It avoids potential truncation or sign conversion mismatch issues. Reviewed-by: Pratyush Yadav (Google) Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Pasha Tatashin --- kernel/liveupdate/luo_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_inter= nal.h index dd53d4a7277e..ae58206f14ac 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -52,7 +52,7 @@ static inline int luo_ucmd_respond(struct luo_ucmd *ucmd, struct luo_file_set { struct list_head files_list; struct luo_file_ser *files; - long count; + u64 count; }; =20 /** --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A92A23D1717 for ; Wed, 3 Jun 2026 15:44:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501469; cv=none; b=Nc1YRDIwzQzsgS/syB76glu2fkid6mMaF+XA8UkqZpslVYPJXUNKEmxH9d6BYvf4QBIOfys+leVn4EhAaxskBVGrpO4s78cTmEGbLvu/cW43IYdII1UiO3BWvcByIeV9seZK0YXTsIerC1GA589TT5GhVQwNLxT2eSpMa3lrky0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501469; c=relaxed/simple; bh=iUmoYAejiLn461xrcMpaIUD7Gez0PFfQeM+9hwbLOIk=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FB5zsbgXGCoC74W3WEaR7r+CmfIDqkBZyeqcFGybsyFZ7E+znp2oOihJCdz61Wu4sOIys4On2aR2BXWP8krDHFxKnxLABe9SPoS0d8CzR5An5sow/lc5Ob5pCUKNnYokJUvP02Nq7I/6fTY8pdv8nTcwXrvcXxYaVT9d6HCii34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=MesSd6mE; arc=none smtp.client-ip=209.85.219.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="MesSd6mE" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-8ce9df31130so55424916d6.1 for ; Wed, 03 Jun 2026 08:44:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501468; x=1781106268; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=i8sI6lLCNHN6RKEMLtPAJ87Qc5cPrvkoDu5wACGhMgc=; b=MesSd6mERZzT3AZATjsAor3hWlZuvtTFFfOos2YTMKc5JqhyjwIHoMrpvAwxrJOfpP 9n8BR2MljG5UYQwpk9I3YDjG5EARPi+SqUe6TDlEb0XZgHXF17qnzSRo7pBKShPp6iP/ oIuz9vL9Mdi8vNErp3EnsvTmikLZ5/TbzXheknr/nouq/9TLjJ9XnoDSTqd+iN0YFLDn kzR6lllYLGtRnasRvoOHlwCu4fEGXJAMqf66f/AgXNdu4NWXJ8ehOIQBJCihXRvTkEaV HTG1DlPlK4C+B/ZEFga0jAyKT8lMsKEPuc1xVPXUgP1WLhAQZMMXybuBWL2cOlmO6S8+ A5xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501468; x=1781106268; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=i8sI6lLCNHN6RKEMLtPAJ87Qc5cPrvkoDu5wACGhMgc=; b=TxBl2kV5aDO3S4SauuaG67+NLJ1r2QHSZrvos3bTGnwAxZHmrmnZAPI5x00ZCuli6C oBHsT4RqnVZtt5+//3EaIRhPvWIJsqbr9o9eeNVk1do3uTp0QLUVxt4cKJpdpH1GKXtC LZgr5h3+eAPEhf7xItGMjISc6mZlmW880ejxeLVhqMsejrxirJoX6HlE4YyOWOSFkHY4 nbSehGKHEU2WBIpk3YcUzDoOUMg6H2qSaKuMppGj+7zGKdK9XODGf0YBDKhGDOtc9BmJ Z/3azAcIJNzPsQ3f4McfQOZOp9qLWWHLs6BlSS7tMe3h1GAKy/R/n/VArr98g1BwvDMj Wm5g== X-Forwarded-Encrypted: i=1; AFNElJ9jEYMwEoLD9oszYXgvgJwT9Nmk8kD7X9vO2E9/wNEAVd0WO6wmDidb7Sqk1qS1cIG3KdwN/aBidu/Fo0Q=@vger.kernel.org X-Gm-Message-State: AOJu0YzSCDm9i7JgbWD5o9dXbaFLrWcQK728ZVoymI/bcv7/zza/Sue2 ZRqAF4Bw0SBMu9WYeb3q8wxH08bLIpAe19XeweXt3RnVeKD3MbhGG7uYhECUYkuw/8w= X-Gm-Gg: Acq92OEqNPFF+gDMre3rfP/ajSkaubMPxCDTXtjthq9t+vNVd2y57IrgKgixapa5KyH 2mEsdccNQH8i1POREX/oKFsWBhpBaGtVY6pbp+YC7oXLtNRAZqxKL5CgmhKuAnHLWW0MYvjExI/ xDlS3S+lrtlwiPbH3L2ymD+iZ47hEct/8+7weBW8CODB3iRH4M/GVpfwFf9ejvS7zxYcd7oOwO3 CvcymJo5N4rX+TEHNKwMRmQRfxNdwxVlTbt0dfVqneB4RjCsIJHQFnt+F5BIz3wE8ztuuPs8ody dkbJkrkoDHpdvY/Av/GiDe/vNrJ7QNQ1i82DyRFk8+PuauxYLIFQ2d4mUhR7GOLECrH3k7Kkeg5 3mM79tFRBWVYivtjrhNRNiekeKqOP+ko6J3AW3efMIVkvP5maSS5msIt+R+RXn0+mooUXSucmSX BRBwCozw1JLal9udU9sZcaxjfRFdT2KE/8we/Zg4nCvw5XOLUtN2SaMDKnqsPtiA== X-Received: by 2002:a05:6214:aca:b0:8bd:6baa:6a0c with SMTP id 6a1803df08f44-8cecdc28301mr58362326d6.11.1780501467702; Wed, 03 Jun 2026 08:44:27 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8cecd0520d3sm23311476d6.27.2026.06.03.08.44.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:44:27 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 02/13] liveupdate: avoid mixing cleanup guards with goto in luo_session_retrieve_fd Date: Wed, 3 Jun 2026 15:43:51 +0000 Message-ID: <20260603154402.468928-3-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactoring luo_session_retrieve_fd() to avoid mixing automated cleanup-style guards with goto-based resource release, which is not recommended under the Linux kernel coding style. Reviewed-by: Pratyush Yadav (Google) Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Pasha Tatashin --- kernel/liveupdate/luo_session.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index 5c6cebc6e326..47566db64598 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -291,10 +291,11 @@ static int luo_session_retrieve_fd(struct luo_session= *session, if (argp->fd < 0) return argp->fd; =20 - guard(mutex)(&session->mutex); + mutex_lock(&session->mutex); err =3D luo_retrieve_file(&session->file_set, argp->token, &file); + mutex_unlock(&session->mutex); if (err < 0) - goto err_put_fd; + goto err_put_fd; =20 err =3D luo_ucmd_respond(ucmd, sizeof(*argp)); if (err) --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 86EC439A063 for ; Wed, 3 Jun 2026 15:44:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501482; cv=none; b=b6fV6DrFshNnW1gIwWMx6CUMNp49Z20NJzcV3tMWBTPLm05fLGACZ5yw9oZ+mEzX+Qj5+ovlak7zfjOnw/zJtlV0ZljObiv3PTW7135VIRCcntNEpC9S29yc+fASH+sOrFdorg1hPusjGh6v78V+EeJXR4+voRzPRxEMiQzT8KQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501482; c=relaxed/simple; bh=QVmsRDiFXVCKsPRBSFGD0zPxGCL3oiGgGgtiExPPR2M=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IFE8xpCArxl1MRXWE9Oidn/51DapYfhgjZDV8n0I7XsZtSFgVVc6gVoFKvNdEiYGhFNPuu5NGS8qk7zuDH6Vylnf6uQBIQd4VSTWaJ6MWCOMbw18KewOYuxky2UIikgcNXWVAoCtvE+gsognkUMrQ2elfq1BB2/xParXqhQMK7U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=UOqSRQTK; arc=none smtp.client-ip=209.85.222.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="UOqSRQTK" Received: by mail-qk1-f181.google.com with SMTP id af79cd13be357-915906a4becso84034885a.2 for ; Wed, 03 Jun 2026 08:44:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501480; x=1781106280; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=qJs3vMWEh5lMBsn2ojdsHtSBK02MSOoqr9r9XS5tsI8=; b=UOqSRQTKx5jn2A1KkeOcRNFjFZDzSCZIfoBQhk6eETFD+ghkGH2hzoWCqR4OQIYWne DDRqkXVwNEGvz0Kn6sF1ZoCJBSSQuD0Hh7yQ82hezyN4l0dHsrO88ItAmYtvwaFEoDQh CdzaBum9bRCAVq1ob3rMwaF+OkIi5dhC4NTLxqTAPU7qt8/yWX9IzsntDIZBS+uUJhUX n6j0TEJ7QYaDmwnqKtPWvOMOTxoRlGwvZUjFmzJRspT8hjlzH2libZrhwEZ9lzNBCYQH RD45Ze7H+zl417Gv0a7qUuJCNDNvXuC5Lfo+VD7BmvOiytSt1bn5JnstRhi7JTMfKbsb XyKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501480; x=1781106280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=qJs3vMWEh5lMBsn2ojdsHtSBK02MSOoqr9r9XS5tsI8=; b=FS0EIUPibauPq0WA/A3Q1mH5GPLi7aL2nAP3HYxigFwC/EngGuaN77i0UoLqNz34sr FfFSo0zUf7GyH1/6uc1u/gvK8JVZGxlO43YyHy5+zyH3OEKcEIeJtQnZr50XGt9WJXkn uOqq2mD/junEKtO2zrD8rFyRklaywOeaLB6dzwElCO5L/mlhT+SCp9w/p6Wn+NffjUug kXp9gs1YWfK6HVrlfW3xwdKtIAV5rbQpCh8sS0BjU6trBylR/eo+rWRf+qzkinHqmnC1 zTTXxmyCMKwXZLN270cvVUCkl0kJRSdocmTF5oCebqylOLPj7wI4ZpIOFmnQ6hHAz5g0 Q0TQ== X-Forwarded-Encrypted: i=1; AFNElJ+82fBHdQX/A14uDy4QZdR/1hAWN6fA9boHQz3ghXxGYhwngxqJVPrKEtxVQHX/W8632H4hrFbjmR4s0jM=@vger.kernel.org X-Gm-Message-State: AOJu0YwxNSmdD2RQW6UJBsbKDcinyo53Rcch7wSsbFgOCG3Sw1FVDz3L UkmhmcVSzLTtedhXOOH1k4VkrQfQ0FBVYIsTnj9NMogGQG1qz6sXGY5bDEITYXq53Pw= X-Gm-Gg: Acq92OEDF1zFWyAqC/mNX7GsGT91iQkysmIlLARRK3f4LTQ0R1lwkPzuVlY3hRcw4E9 vjlWlQ8/9LQVTTv/9IHN751+DeZ39MrIkSEVUmajfpQefETZjAmiUPcd3HCW0Wsrxv/hCiQEXaW f45g6PJwl0jLO2H+LkMA1x4MGACJyYmyB8/P1b9RqeT+r4U5/Y6HM4suCGEgAsorbjAdIMU6es9 C3lzhgnxE9fm/LspJJNuwYc0lES8YgDtq0qYgLamP/d3aoB0IDrVdUk3nJSpx5bcAfgex+7XBct 7O6Kz83J0RqH3wjQVfznvVGmMyAJoUAv9iABeynJ3b3Mi3bIBWhLCq6xfBqQw4bF5DfRvgQFtLr cHmPUnbc3lNghurU3tynTHlGJXmtaPjcoWW2vGzlgXMD73TDAVT7XHKN/LqmgFYqNGi0oYs0xXj I9Fg9tuSjHDUHGJ4thbvfRKjRloOgdiUmr72HXYJplSmyceyoorA3Q4dBB8WsVtw== X-Received: by 2002:a05:620a:470d:b0:915:6c4e:4c61 with SMTP id af79cd13be357-9158a6af95cmr662265185a.24.1780501479496; Wed, 03 Jun 2026 08:44:39 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a009fb2sm287423185a.5.2026.06.03.08.44.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:44:39 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 03/13] liveupdate: centralize state management into struct luo_ser Date: Wed, 3 Jun 2026 15:43:52 +0000 Message-ID: <20260603154402.468928-4-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Transition the LUO to ABI v2, which centralizes state management into a single struct luo_ser header. Previously, LUO state was spread across multiple FDT properties and subnodes. ABI v2 simplifies this by placing all core state, including the liveupdate number and physical addresses for sessions and FLB headers into a centralized struct luo_ser. Note that this change introduces a semantic difference: the sessions and FLB serialization formats are no longer completely independent of the core LUO. Their metadata (such as physical addresses for sessions and FLB headers) is now coupled to and managed via the centralized struct luo_ser. Reviewed-by: Pratyush Yadav (Google) Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Pasha Tatashin --- include/linux/kho/abi/luo.h | 91 +++++++++++--------------------- kernel/liveupdate/luo_core.c | 64 +++++++++++++++------- kernel/liveupdate/luo_flb.c | 60 +++------------------ kernel/liveupdate/luo_internal.h | 8 +-- kernel/liveupdate/luo_session.c | 64 ++++------------------ 5 files changed, 96 insertions(+), 191 deletions(-) diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h index 46750a0ddf88..1b2f865a771a 100644 --- a/include/linux/kho/abi/luo.h +++ b/include/linux/kho/abi/luo.h @@ -30,52 +30,25 @@ * .. code-block:: none * * / { - * compatible =3D "luo-v1"; - * liveupdate-number =3D <...>; - * - * luo-session { - * compatible =3D "luo-session-v1"; - * luo-session-header =3D ; - * }; - * - * luo-flb { - * compatible =3D "luo-flb-v1"; - * luo-flb-header =3D ; - * }; + * compatible =3D "luo-v2"; + * luo-abi-header =3D ; * }; * * Main LUO Node (/): * - * - compatible: "luo-v1" + * - compatible: "luo-v2" * Identifies the overall LUO ABI version. - * - liveupdate-number: u64 - * A counter tracking the number of successful live updates performed. - * - * Session Node (luo-session): - * This node describes all preserved user-space sessions. - * - * - compatible: "luo-session-v1" - * Identifies the session ABI version. - * - luo-session-header: u64 - * The physical address of a `struct luo_session_header_ser`. This str= ucture - * is the header for a contiguous block of memory containing an array = of - * `struct luo_session_ser`, one for each preserved session. - * - * File-Lifecycle-Bound Node (luo-flb): - * This node describes all preserved global objects whose lifecycle is b= ound - * to that of the preserved files (e.g., shared IOMMU state). - * - * - compatible: "luo-flb-v1" - * Identifies the FLB ABI version. - * - luo-flb-header: u64 - * The physical address of a `struct luo_flb_header_ser`. This structu= re is - * the header for a contiguous block of memory containing an array of - * `struct luo_flb_ser`, one for each preserved global object. + * - luo-abi-header: u64 + * The physical address of `struct luo_ser`. * * Serialization Structures: * The FDT properties point to memory regions containing arrays of simpl= e, * `__packed` structures. These structures contain the actual preserved = state. * + * - struct luo_ser: + * The central ABI structure that contains the overall state of the LU= O. + * It includes the liveupdate-number and pointers to sessions and FLBs. + * * - struct luo_session_header_ser: * Header for the session array. Contains the total page count of the * preserved memory block and the number of `struct luo_session_ser` @@ -109,13 +82,26 @@ =20 /* * The LUO FDT hooks all LUO state for sessions, fds, etc. - * In the root it also carries "liveupdate-number" 64-bit property that - * corresponds to the number of live-updates performed on this machine. */ #define LUO_FDT_SIZE PAGE_SIZE #define LUO_FDT_KHO_ENTRY_NAME "LUO" -#define LUO_FDT_COMPATIBLE "luo-v1" -#define LUO_FDT_LIVEUPDATE_NUM "liveupdate-number" +#define LUO_FDT_COMPATIBLE "luo-v2" +#define LUO_FDT_ABI_HEADER "luo-abi-header" + +/** + * struct luo_ser - Centralized LUO ABI header. + * @liveupdate_num: A counter tracking the number of successful live updat= es. + * @sessions_pa: Physical address of the first session block header. + * @flbs_pa: Physical address of the FLB header. + * + * This structure is the root of all preserved LUO state. It is pointed to= by + * the "luo-abi-header" property in the LUO FDT. + */ +struct luo_ser { + u64 liveupdate_num; + u64 sessions_pa; + u64 flbs_pa; +} __packed; =20 #define LIVEUPDATE_HNDL_COMPAT_LENGTH 48 =20 @@ -147,15 +133,6 @@ struct luo_file_set_ser { u64 count; } __packed; =20 -/* - * LUO FDT session node - * LUO_FDT_SESSION_HEADER: is a u64 physical address of struct - * luo_session_header_ser - */ -#define LUO_FDT_SESSION_NODE_NAME "luo-session" -#define LUO_FDT_SESSION_COMPATIBLE "luo-session-v2" -#define LUO_FDT_SESSION_HEADER "luo-session-header" - /** * struct luo_session_header_ser - Header for the serialized session data = block. * @count: The number of `struct luo_session_ser` entries that immediately @@ -165,7 +142,7 @@ struct luo_file_set_ser { * physical memory preserved across the kexec. It provides the necessary * metadata to interpret the array of session entries that follow. * - * If this structure is modified, `LUO_FDT_SESSION_COMPATIBLE` must be upd= ated. + * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. */ struct luo_session_header_ser { u64 count; @@ -182,7 +159,7 @@ struct luo_session_header_ser { * session) is created and passed to the new kernel, allowing it to recons= truct * the session context. * - * If this structure is modified, `LUO_FDT_SESSION_COMPATIBLE` must be upd= ated. + * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. */ struct luo_session_ser { char name[LIVEUPDATE_SESSION_NAME_LENGTH]; @@ -192,10 +169,6 @@ struct luo_session_ser { /* The max size is set so it can be reliably used during in serialization = */ #define LIVEUPDATE_FLB_COMPAT_LENGTH 48 =20 -#define LUO_FDT_FLB_NODE_NAME "luo-flb" -#define LUO_FDT_FLB_COMPATIBLE "luo-flb-v1" -#define LUO_FDT_FLB_HEADER "luo-flb-header" - /** * struct luo_flb_header_ser - Header for the serialized FLB data block. * @pgcnt: The total number of pages occupied by the entire preserved memo= ry @@ -205,11 +178,9 @@ struct luo_session_ser { * in the memory block. * * This structure is located at the physical address specified by the - * `LUO_FDT_FLB_HEADER` FDT property. It provides the new kernel with the - * necessary information to find and iterate over the array of preserved - * File-Lifecycle-Bound objects and to manage the underlying memory. + * flbs_pa in luo_ser. * - * If this structure is modified, LUO_FDT_FLB_COMPATIBLE must be updated. + * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. */ struct luo_flb_header_ser { u64 pgcnt; @@ -231,7 +202,7 @@ struct luo_flb_header_ser { * passed to the new kernel. Each entry allows the LUO core to restore one * global, shared object. * - * If this structure is modified, LUO_FDT_FLB_COMPATIBLE must be updated. + * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. */ struct luo_flb_ser { char name[LIVEUPDATE_FLB_COMPAT_LENGTH]; diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 5d5827ced73c..085c0dfc1ef1 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -61,7 +61,6 @@ #include #include #include -#include =20 #include "kexec_handover_internal.h" #include "luo_internal.h" @@ -86,9 +85,11 @@ early_param("liveupdate", early_liveupdate_param); =20 static int __init luo_early_startup(void) { + struct luo_ser *luo_ser; + int err, header_size; phys_addr_t fdt_phys; - int err, ln_size; const void *ptr; + u64 luo_ser_pa; =20 if (!kho_is_enabled()) { if (liveupdate_enabled()) @@ -119,26 +120,32 @@ static int __init luo_early_startup(void) return -EINVAL; } =20 - ln_size =3D 0; - ptr =3D fdt_getprop(luo_global.fdt_in, 0, LUO_FDT_LIVEUPDATE_NUM, - &ln_size); - if (!ptr || ln_size !=3D sizeof(luo_global.liveupdate_num)) { - pr_err("Unable to get live update number '%s' [%d]\n", - LUO_FDT_LIVEUPDATE_NUM, ln_size); + header_size =3D 0; + ptr =3D fdt_getprop(luo_global.fdt_in, 0, LUO_FDT_ABI_HEADER, &header_siz= e); + if (!ptr || header_size !=3D sizeof(u64)) { + pr_err("Unable to get ABI header '%s' [%d]\n", + LUO_FDT_ABI_HEADER, header_size); =20 return -EINVAL; } =20 - luo_global.liveupdate_num =3D get_unaligned((u64 *)ptr); + luo_ser_pa =3D get_unaligned((u64 *)ptr); + luo_ser =3D phys_to_virt(luo_ser_pa); + + luo_global.liveupdate_num =3D luo_ser->liveupdate_num; pr_info("Retrieved live update data, liveupdate number: %lld\n", luo_global.liveupdate_num); =20 - err =3D luo_session_setup_incoming(luo_global.fdt_in); + err =3D luo_session_setup_incoming(luo_ser->sessions_pa); if (err) - return err; + goto out_free_ser; + + luo_flb_setup_incoming(luo_ser->flbs_pa); =20 - err =3D luo_flb_setup_incoming(luo_global.fdt_in); + err =3D 0; =20 +out_free_ser: + kho_restore_free(luo_ser); return err; } =20 @@ -160,7 +167,8 @@ early_initcall(liveupdate_early_init); /* Called during boot to create outgoing LUO fdt tree */ static int __init luo_fdt_setup(void) { - const u64 ln =3D luo_global.liveupdate_num + 1; + struct luo_ser *luo_ser; + u64 luo_ser_pa; void *fdt_out; int err; =20 @@ -170,27 +178,45 @@ static int __init luo_fdt_setup(void) return PTR_ERR(fdt_out); } =20 + luo_ser =3D kho_alloc_preserve(sizeof(*luo_ser)); + if (IS_ERR(luo_ser)) { + err =3D PTR_ERR(luo_ser); + goto exit_free_fdt; + } + luo_ser_pa =3D virt_to_phys(luo_ser); + err =3D fdt_create(fdt_out, LUO_FDT_SIZE); err |=3D fdt_finish_reservemap(fdt_out); err |=3D fdt_begin_node(fdt_out, ""); err |=3D fdt_property_string(fdt_out, "compatible", LUO_FDT_COMPATIBLE); - err |=3D fdt_property(fdt_out, LUO_FDT_LIVEUPDATE_NUM, &ln, sizeof(ln)); - err |=3D luo_session_setup_outgoing(fdt_out); - err |=3D luo_flb_setup_outgoing(fdt_out); + err |=3D fdt_property(fdt_out, LUO_FDT_ABI_HEADER, &luo_ser_pa, + sizeof(luo_ser_pa)); err |=3D fdt_end_node(fdt_out); err |=3D fdt_finish(fdt_out); if (err) - goto exit_free; + goto exit_free_luo_ser; + + err =3D luo_session_setup_outgoing(&luo_ser->sessions_pa); + if (err) + goto exit_free_luo_ser; + + err =3D luo_flb_setup_outgoing(&luo_ser->flbs_pa); + if (err) + goto exit_free_luo_ser; + + luo_ser->liveupdate_num =3D luo_global.liveupdate_num + 1; =20 err =3D kho_add_subtree(LUO_FDT_KHO_ENTRY_NAME, fdt_out, fdt_totalsize(fdt_out)); if (err) - goto exit_free; + goto exit_free_luo_ser; luo_global.fdt_out =3D fdt_out; =20 return 0; =20 -exit_free: +exit_free_luo_ser: + kho_unpreserve_free(luo_ser); +exit_free_fdt: kho_unpreserve_free(fdt_out); pr_err("failed to prepare LUO FDT: %d\n", err); =20 diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c index 8f5c5dd01cd0..5c27134ce7ba 100644 --- a/kernel/liveupdate/luo_flb.c +++ b/kernel/liveupdate/luo_flb.c @@ -44,13 +44,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include "luo_internal.h" =20 #define LUO_FLB_PGCNT 1ul @@ -551,27 +549,15 @@ int liveupdate_flb_get_outgoing(struct liveupdate_flb= *flb, void **objp) return 0; } =20 -int __init luo_flb_setup_outgoing(void *fdt_out) +int __init luo_flb_setup_outgoing(u64 *flbs_pa) { struct luo_flb_header_ser *header_ser; - u64 header_ser_pa; - int err; =20 header_ser =3D kho_alloc_preserve(LUO_FLB_PGCNT << PAGE_SHIFT); if (IS_ERR(header_ser)) return PTR_ERR(header_ser); =20 - header_ser_pa =3D virt_to_phys(header_ser); - - err =3D fdt_begin_node(fdt_out, LUO_FDT_FLB_NODE_NAME); - err |=3D fdt_property_string(fdt_out, "compatible", - LUO_FDT_FLB_COMPATIBLE); - err |=3D fdt_property(fdt_out, LUO_FDT_FLB_HEADER, &header_ser_pa, - sizeof(header_ser_pa)); - err |=3D fdt_end_node(fdt_out); - - if (err) - goto err_unpreserve; + *flbs_pa =3D virt_to_phys(header_ser); =20 header_ser->pgcnt =3D LUO_FLB_PGCNT; luo_flb_global.outgoing.header_ser =3D header_ser; @@ -579,53 +565,19 @@ int __init luo_flb_setup_outgoing(void *fdt_out) luo_flb_global.outgoing.active =3D true; =20 return 0; - -err_unpreserve: - kho_unpreserve_free(header_ser); - - return err; } =20 -int __init luo_flb_setup_incoming(void *fdt_in) +void __init luo_flb_setup_incoming(u64 flbs_pa) { struct luo_flb_header_ser *header_ser; - int err, header_size, offset; - const void *ptr; - u64 header_ser_pa; - - offset =3D fdt_subnode_offset(fdt_in, 0, LUO_FDT_FLB_NODE_NAME); - if (offset < 0) { - pr_err("Unable to get FLB node [%s]\n", LUO_FDT_FLB_NODE_NAME); - - return -ENOENT; - } - - err =3D fdt_node_check_compatible(fdt_in, offset, - LUO_FDT_FLB_COMPATIBLE); - if (err) { - pr_err("FLB node is incompatible with '%s' [%d]\n", - LUO_FDT_FLB_COMPATIBLE, err); - - return -EINVAL; - } - - header_size =3D 0; - ptr =3D fdt_getprop(fdt_in, offset, LUO_FDT_FLB_HEADER, &header_size); - if (!ptr || header_size !=3D sizeof(u64)) { - pr_err("Unable to get FLB header property '%s' [%d]\n", - LUO_FDT_FLB_HEADER, header_size); =20 - return -EINVAL; - } - - header_ser_pa =3D get_unaligned((u64 *)ptr); - header_ser =3D phys_to_virt(header_ser_pa); + if (!flbs_pa) + return; =20 + header_ser =3D phys_to_virt(flbs_pa); luo_flb_global.incoming.header_ser =3D header_ser; luo_flb_global.incoming.ser =3D (void *)(header_ser + 1); luo_flb_global.incoming.active =3D true; - - return 0; } =20 /** diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_inter= nal.h index ae58206f14ac..fe22086bfbeb 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -79,8 +79,8 @@ extern struct rw_semaphore luo_register_rwlock; =20 int luo_session_create(const char *name, struct file **filep); int luo_session_retrieve(const char *name, struct file **filep); -int __init luo_session_setup_outgoing(void *fdt); -int __init luo_session_setup_incoming(void *fdt); +int __init luo_session_setup_outgoing(u64 *sessions_pa); +int __init luo_session_setup_incoming(u64 sessions_pa); int luo_session_serialize(void); int luo_session_deserialize(void); =20 @@ -102,8 +102,8 @@ int luo_flb_file_preserve(struct liveupdate_file_handle= r *fh); void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh); void luo_flb_file_finish(struct liveupdate_file_handler *fh); void luo_flb_unregister_all(struct liveupdate_file_handler *fh); -int __init luo_flb_setup_outgoing(void *fdt); -int __init luo_flb_setup_incoming(void *fdt); +int __init luo_flb_setup_outgoing(u64 *flbs_pa); +void __init luo_flb_setup_incoming(u64 flbs_pa); void luo_flb_serialize(void); =20 #ifdef CONFIG_LIVEUPDATE_TEST diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index 47566db64598..85782c6f3d6c 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -25,9 +25,8 @@ * * - Serialization: Session metadata is preserved using the KHO framework.= When * a live update is triggered via kexec, an array of `struct luo_session= _ser` - * is populated and placed in a preserved memory region. An FDT node is = also - * created, containing the count of sessions and the physical address of= this - * array. + * is populated and placed in a preserved memory region. The physical ad= dress + * of this array is stored in the centralized `struct luo_ser` structure. * * Session Lifecycle: * @@ -91,13 +90,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include "luo_internal.h" =20 @@ -527,75 +524,34 @@ int luo_session_retrieve(const char *name, struct fil= e **filep) return err; } =20 -int __init luo_session_setup_outgoing(void *fdt_out) +int __init luo_session_setup_outgoing(u64 *sessions_pa) { struct luo_session_header_ser *header_ser; - u64 header_ser_pa; - int err; =20 header_ser =3D kho_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT); if (IS_ERR(header_ser)) return PTR_ERR(header_ser); - header_ser_pa =3D virt_to_phys(header_ser); - - err =3D fdt_begin_node(fdt_out, LUO_FDT_SESSION_NODE_NAME); - err |=3D fdt_property_string(fdt_out, "compatible", - LUO_FDT_SESSION_COMPATIBLE); - err |=3D fdt_property(fdt_out, LUO_FDT_SESSION_HEADER, &header_ser_pa, - sizeof(header_ser_pa)); - err |=3D fdt_end_node(fdt_out); =20 - if (err) - goto err_unpreserve; + *sessions_pa =3D virt_to_phys(header_ser); =20 luo_session_global.outgoing.header_ser =3D header_ser; luo_session_global.outgoing.ser =3D (void *)(header_ser + 1); luo_session_global.outgoing.active =3D true; =20 return 0; - -err_unpreserve: - kho_unpreserve_free(header_ser); - return err; } =20 -int __init luo_session_setup_incoming(void *fdt_in) +int __init luo_session_setup_incoming(u64 sessions_pa) { struct luo_session_header_ser *header_ser; - int err, header_size, offset; - u64 header_ser_pa; - const void *ptr; - - offset =3D fdt_subnode_offset(fdt_in, 0, LUO_FDT_SESSION_NODE_NAME); - if (offset < 0) { - pr_err("Unable to get session node: [%s]\n", - LUO_FDT_SESSION_NODE_NAME); - return -EINVAL; - } =20 - err =3D fdt_node_check_compatible(fdt_in, offset, - LUO_FDT_SESSION_COMPATIBLE); - if (err) { - pr_err("Session node incompatible [%s]\n", - LUO_FDT_SESSION_COMPATIBLE); - return -EINVAL; - } - - header_size =3D 0; - ptr =3D fdt_getprop(fdt_in, offset, LUO_FDT_SESSION_HEADER, &header_size); - if (!ptr || header_size !=3D sizeof(u64)) { - pr_err("Unable to get session header '%s' [%d]\n", - LUO_FDT_SESSION_HEADER, header_size); - return -EINVAL; + if (sessions_pa) { + header_ser =3D phys_to_virt(sessions_pa); + luo_session_global.incoming.header_ser =3D header_ser; + luo_session_global.incoming.ser =3D (void *)(header_ser + 1); + luo_session_global.incoming.active =3D true; } =20 - header_ser_pa =3D get_unaligned((u64 *)ptr); - header_ser =3D phys_to_virt(header_ser_pa); - - luo_session_global.incoming.header_ser =3D header_ser; - luo_session_global.incoming.ser =3D (void *)(header_ser + 1); - luo_session_global.incoming.active =3D true; - return 0; } =20 --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qv1-f52.google.com (mail-qv1-f52.google.com [209.85.219.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C5793D3329 for ; Wed, 3 Jun 2026 15:44:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501494; cv=none; b=Fj7cM8CxDhEW4VvatgseElwVsWvA2PB+He+DTyjmx44WGkXbCXSmBjXLKfoJL6eOJKsUKyDfqd3ACe6UfI6u2I/U1oSl3DJqGCA0xx+8Wjw8CMxG03Q52zSxIfd3t6ZYen9qeE3MiFG+iURD7Jz2Ol+hO9vJHr7VIDWK2DH3pUU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501494; c=relaxed/simple; bh=SFW+rOyUIbjjg2bkYM14MG0vqxdh1g+TRvzBdcb0ifM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=A4Xvh3+KoQOAGrZmXzP4exZerWs9fYY/2DIRJrt/mz3YBuukID1hylXoCKBkMql0GfZjcDdp7EiXfY/MCi0eL71/CS99/2o0rftQU5Qiq1v/IGdEKrabRUVAX4tMlokjAo7rcMs36kroM6UIcy44oiW9nwLPy7avuLYrZGcJx4w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=M90HgRzw; arc=none smtp.client-ip=209.85.219.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="M90HgRzw" Received: by mail-qv1-f52.google.com with SMTP id 6a1803df08f44-8cd45d4b7e2so49872546d6.2 for ; Wed, 03 Jun 2026 08:44:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501491; x=1781106291; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ysXJwhFF5ZMhelrNqugrHKhMpfhNNGitYhajZTivsf4=; b=M90HgRzw2Z4BLmNQS8qPYP9SCI8JYxjwbjRMiMMT8jiiEchj43oCXBW0I+S8x1H/wP 3FlhF4OklqfNXcSZQRZDgRwgtA1I4uXWKPDyLBWCvNLbyB9WES8ITur+KUCdkN8EdR0u g3mF8y1L+t79A34woTtmYqH8Kw/BuW436yUb75W0ocLxx99LOqbh4N+7vXbpr4nAREIB LSjIv5t6VcyEE6iDrT7krm6pFj6BPFn+AvfhmXoMee8rNqtU579IadTwCoeOcFiJnwdl SDEpr8WKyiKBM/iqNP0D5+RIYbL7fFsO7vSHh74WKPViv8fWFAwVIv/ilzN4lK8ymgj1 vxIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501491; x=1781106291; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=ysXJwhFF5ZMhelrNqugrHKhMpfhNNGitYhajZTivsf4=; b=H3yOUeqJbNg413NffOfThZ7hjS8ubC2w2xwmoDrKItZUdoATNg9SH3tAPXZ4r01ot9 v8pNClUcN0gQHxMexecw8IT3fHNzKHjQ9AKrEI3A0xGUauBQQpXO3Sj3rkGge2Ghnvvl p2rPWe1n0zZefhk64MdOLDl3gpxxo6y53GuvT4jUQYPCxiHIAeDEDAgEr3oMPK64yF1b geB9ozBeExLTsDSQUzwt0Hi52ozfBSPG158FJ0NCHKh+7n3L6F+Sworj+CqtF06zcRrC bZ7AFcFTXjraazs5WeyK3YBG/Ai1mRtk63zyXC52z2OFqYdmRXBAvmS7jKVMI0iZpux3 WTcQ== X-Forwarded-Encrypted: i=1; AFNElJ8Dmn0BQlHz+i5uJggaiO1Yn67BQQIh8l1KHCReSHv+oGJA+lPjo6gAgFp4BVaG1TnjQRs+pCfMu39ZVbI=@vger.kernel.org X-Gm-Message-State: AOJu0YwV5DLDn5ng38OsEZMQSiGEcIP+MlVDlIFw4vWff5gdk+vMdqXT r7vzHNL9pN7tAaCHbg0xnIShgVqhUkv4dZJ1U2JqlPPbgRFiu4zioPssxjWG+hDJe+U= X-Gm-Gg: Acq92OHu+VeAueZTiwOvYTfIoBqWKJLPosNhf8yPIcylA2uvH/MykTP0F129Tza9onv 29dD9X0+SLQ3APh/WT6yVKzGJjN2LlCZ9fXunjRRjYQlTzt9OALf1JfxTCc9E8IcpgO6JhvLWrK CBVs2kPDmASAWAdIyavwx/UzkkiYcXR6WTIRXMZiRJ9cPL1OPISEdIwD7MzTicCd1u53TqEnPjI QgZjhelSwUzXUzwLvSBI+dsAnQrvE/2hZVnmWdnIUJz4pbgnLC4s/MCh52US4qB2n2aCrThM9ao s2p+84JW88g64La1QY2rfMEQRKEAWdJXtljgoa32ZUkDi0ERsBamyvWLN/pgWZh4aK/gG8fk7Kv X2jp+AyAmNSZG1S1Xr5WchLKSmS6dKzyXFYv4nuS2eT94IwkuzM//4jx2Nd3x6AuxYWUgxqLEcE G8YXwzvgJyQBxBOD0b+D4cHryeN9RMLXInwB84yH6OzMr0qiGMh7L/MWQNCPHFjdWR1p4Sb0Rg X-Received: by 2002:a05:6214:40a:b0:8ce:cda0:4c69 with SMTP id 6a1803df08f44-8cecdca714bmr61767996d6.27.1780501491307; Wed, 03 Jun 2026 08:44:51 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8cecd07629dsm23188206d6.39.2026.06.03.08.44.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:44:50 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 04/13] liveupdate: register luo_ser as KHO subtree Date: Wed, 3 Jun 2026 15:43:53 +0000 Message-ID: <20260603154402.468928-5-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Entirely remove the LUO FDT wrapper since the FDT only carries the compatible string and the pointer to the centralized struct luo_ser. Instead, register the struct luo_ser via the KHO raw subtree API, placing the compatibility string inside the structure itself. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- include/linux/kho/abi/luo.h | 57 +++++++++--------------- kernel/liveupdate/luo_core.c | 85 +++++++++++------------------------- 2 files changed, 46 insertions(+), 96 deletions(-) diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h index 1b2f865a771a..9a4fe491812b 100644 --- a/include/linux/kho/abi/luo.h +++ b/include/linux/kho/abi/luo.h @@ -10,11 +10,11 @@ * * Live Update Orchestrator uses the stable Application Binary Interface * defined below to pass state from a pre-update kernel to a post-update - * kernel. The ABI is built upon the Kexec HandOver framework and uses a - * Flattened Device Tree to describe the preserved data. + * kernel. The ABI is built upon the Kexec HandOver framework and registers + * the central `struct luo_ser` via the KHO raw subtree API. * - * This interface is a contract. Any modification to the FDT structure, no= de - * properties, compatible strings, or the layout of the `__packed` seriali= zation + * This interface is a contract. Any modification to the structure fields, + * compatible strings, or the layout of the `__packed` serialization * structures defined here constitutes a breaking change. Such changes req= uire * incrementing the version number in the relevant `_COMPATIBLE` string to * prevent a new kernel from misinterpreting data from an old kernel. @@ -23,31 +23,15 @@ * however, backward/forward compatibility is only guaranteed for kernels * supporting the same ABI version. * - * FDT Structure Overview: + * KHO Structure Overview: * The entire LUO state is encapsulated within a single KHO entry named = "LUO". - * This entry contains an FDT with the following layout: - * - * .. code-block:: none - * - * / { - * compatible =3D "luo-v2"; - * luo-abi-header =3D ; - * }; - * - * Main LUO Node (/): - * - * - compatible: "luo-v2" - * Identifies the overall LUO ABI version. - * - luo-abi-header: u64 - * The physical address of `struct luo_ser`. + * This entry contains the `struct luo_ser` structure. * * Serialization Structures: - * The FDT properties point to memory regions containing arrays of simpl= e, - * `__packed` structures. These structures contain the actual preserved = state. - * * - struct luo_ser: * The central ABI structure that contains the overall state of the LU= O. - * It includes the liveupdate-number and pointers to sessions and FLBs. + * It includes the compatibility string, the liveupdate-number, and po= inters + * to sessions and FLBs. * * - struct luo_session_header_ser: * Header for the session array. Contains the total page count of the @@ -78,26 +62,27 @@ #ifndef _LINUX_KHO_ABI_LUO_H #define _LINUX_KHO_ABI_LUO_H =20 +#include #include =20 /* - * The LUO FDT hooks all LUO state for sessions, fds, etc. + * The LUO state is registered under this KHO entry name. */ -#define LUO_FDT_SIZE PAGE_SIZE -#define LUO_FDT_KHO_ENTRY_NAME "LUO" -#define LUO_FDT_COMPATIBLE "luo-v2" -#define LUO_FDT_ABI_HEADER "luo-abi-header" +#define LUO_KHO_ENTRY_NAME "LUO" +#define LUO_ABI_COMPATIBLE "luo-v3" +#define LUO_ABI_COMPAT_LEN ALIGN(sizeof(LUO_ABI_COMPATIBLE), 8) =20 /** * struct luo_ser - Centralized LUO ABI header. + * @compatible: Compatibility string identifying the LUO ABI version. * @liveupdate_num: A counter tracking the number of successful live updat= es. * @sessions_pa: Physical address of the first session block header. * @flbs_pa: Physical address of the FLB header. * - * This structure is the root of all preserved LUO state. It is pointed to= by - * the "luo-abi-header" property in the LUO FDT. + * This structure is the root of all preserved LUO state. */ struct luo_ser { + char compatible[LUO_ABI_COMPAT_LEN]; u64 liveupdate_num; u64 sessions_pa; u64 flbs_pa; @@ -111,7 +96,7 @@ struct luo_ser { * @data: Private data * @token: User provided token for this file * - * If this structure is modified, LUO_SESSION_COMPATIBLE must be updated. + * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated. */ struct luo_file_ser { char compatible[LIVEUPDATE_HNDL_COMPAT_LENGTH]; @@ -142,7 +127,7 @@ struct luo_file_set_ser { * physical memory preserved across the kexec. It provides the necessary * metadata to interpret the array of session entries that follow. * - * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. + * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated. */ struct luo_session_header_ser { u64 count; @@ -159,7 +144,7 @@ struct luo_session_header_ser { * session) is created and passed to the new kernel, allowing it to recons= truct * the session context. * - * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. + * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated. */ struct luo_session_ser { char name[LIVEUPDATE_SESSION_NAME_LENGTH]; @@ -180,7 +165,7 @@ struct luo_session_ser { * This structure is located at the physical address specified by the * flbs_pa in luo_ser. * - * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. + * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated. */ struct luo_flb_header_ser { u64 pgcnt; @@ -202,7 +187,7 @@ struct luo_flb_header_ser { * passed to the new kernel. Each entry allows the LUO core to restore one * global, shared object. * - * If this structure is modified, `LUO_FDT_COMPATIBLE` must be updated. + * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated. */ struct luo_flb_ser { char name[LIVEUPDATE_FLB_COMPAT_LENGTH]; diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 085c0dfc1ef1..69b00e7d0f8f 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include @@ -67,8 +66,7 @@ =20 static struct { bool enabled; - void *fdt_out; - void *fdt_in; + struct luo_ser *luo_ser_out; u64 liveupdate_num; } luo_global; =20 @@ -85,11 +83,10 @@ early_param("liveupdate", early_liveupdate_param); =20 static int __init luo_early_startup(void) { + phys_addr_t luo_ser_phys; struct luo_ser *luo_ser; - int err, header_size; - phys_addr_t fdt_phys; - const void *ptr; - u64 luo_ser_pa; + size_t len; + int err; =20 if (!kho_is_enabled()) { if (liveupdate_enabled()) @@ -98,40 +95,29 @@ static int __init luo_early_startup(void) return 0; } =20 - /* Retrieve LUO subtree, and verify its format. */ - err =3D kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys, NULL); + /* Retrieve LUO state from KHO. */ + err =3D kho_retrieve_subtree(LUO_KHO_ENTRY_NAME, &luo_ser_phys, &len); if (err) { if (err !=3D -ENOENT) { - pr_err("failed to retrieve FDT '%s' from KHO: %pe\n", - LUO_FDT_KHO_ENTRY_NAME, ERR_PTR(err)); + pr_err("failed to retrieve LUO state '%s' from KHO: %pe\n", + LUO_KHO_ENTRY_NAME, ERR_PTR(err)); return err; } =20 return 0; } =20 - luo_global.fdt_in =3D phys_to_virt(fdt_phys); - err =3D fdt_node_check_compatible(luo_global.fdt_in, 0, - LUO_FDT_COMPATIBLE); - if (err) { - pr_err("FDT '%s' is incompatible with '%s' [%d]\n", - LUO_FDT_KHO_ENTRY_NAME, LUO_FDT_COMPATIBLE, err); - + if (len < sizeof(*luo_ser)) { + pr_err("LUO state is too small (%zu < %zu)\n", len, sizeof(*luo_ser)); return -EINVAL; } =20 - header_size =3D 0; - ptr =3D fdt_getprop(luo_global.fdt_in, 0, LUO_FDT_ABI_HEADER, &header_siz= e); - if (!ptr || header_size !=3D sizeof(u64)) { - pr_err("Unable to get ABI header '%s' [%d]\n", - LUO_FDT_ABI_HEADER, header_size); - + luo_ser =3D phys_to_virt(luo_ser_phys); + if (strncmp(luo_ser->compatible, LUO_ABI_COMPATIBLE, LUO_ABI_COMPAT_LEN))= { + pr_err("LUO state is incompatible with '%s'\n", LUO_ABI_COMPATIBLE); return -EINVAL; } =20 - luo_ser_pa =3D get_unaligned((u64 *)ptr); - luo_ser =3D phys_to_virt(luo_ser_pa); - luo_global.liveupdate_num =3D luo_ser->liveupdate_num; pr_info("Retrieved live update data, liveupdate number: %lld\n", luo_global.liveupdate_num); @@ -164,37 +150,20 @@ static int __init liveupdate_early_init(void) } early_initcall(liveupdate_early_init); =20 -/* Called during boot to create outgoing LUO fdt tree */ -static int __init luo_fdt_setup(void) +/* Called during boot to create outgoing LUO state */ +static int __init luo_state_setup(void) { struct luo_ser *luo_ser; - u64 luo_ser_pa; - void *fdt_out; int err; =20 - fdt_out =3D kho_alloc_preserve(LUO_FDT_SIZE); - if (IS_ERR(fdt_out)) { - pr_err("failed to allocate/preserve FDT memory\n"); - return PTR_ERR(fdt_out); - } - luo_ser =3D kho_alloc_preserve(sizeof(*luo_ser)); if (IS_ERR(luo_ser)) { - err =3D PTR_ERR(luo_ser); - goto exit_free_fdt; + pr_err("failed to allocate/preserve LUO state memory\n"); + return PTR_ERR(luo_ser); } - luo_ser_pa =3D virt_to_phys(luo_ser); - - err =3D fdt_create(fdt_out, LUO_FDT_SIZE); - err |=3D fdt_finish_reservemap(fdt_out); - err |=3D fdt_begin_node(fdt_out, ""); - err |=3D fdt_property_string(fdt_out, "compatible", LUO_FDT_COMPATIBLE); - err |=3D fdt_property(fdt_out, LUO_FDT_ABI_HEADER, &luo_ser_pa, - sizeof(luo_ser_pa)); - err |=3D fdt_end_node(fdt_out); - err |=3D fdt_finish(fdt_out); - if (err) - goto exit_free_luo_ser; + + strscpy(luo_ser->compatible, LUO_ABI_COMPATIBLE, sizeof(luo_ser->compatib= le)); + luo_ser->liveupdate_num =3D luo_global.liveupdate_num + 1; =20 err =3D luo_session_setup_outgoing(&luo_ser->sessions_pa); if (err) @@ -204,21 +173,17 @@ static int __init luo_fdt_setup(void) if (err) goto exit_free_luo_ser; =20 - luo_ser->liveupdate_num =3D luo_global.liveupdate_num + 1; - - err =3D kho_add_subtree(LUO_FDT_KHO_ENTRY_NAME, fdt_out, - fdt_totalsize(fdt_out)); + err =3D kho_add_subtree(LUO_KHO_ENTRY_NAME, luo_ser, sizeof(*luo_ser)); if (err) goto exit_free_luo_ser; - luo_global.fdt_out =3D fdt_out; + + luo_global.luo_ser_out =3D luo_ser; =20 return 0; =20 exit_free_luo_ser: kho_unpreserve_free(luo_ser); -exit_free_fdt: - kho_unpreserve_free(fdt_out); - pr_err("failed to prepare LUO FDT: %d\n", err); + pr_err("failed to prepare LUO state: %d\n", err); =20 return err; } @@ -234,7 +199,7 @@ static int __init luo_late_startup(void) if (!liveupdate_enabled()) return 0; =20 - err =3D luo_fdt_setup(); + err =3D luo_state_setup(); if (err) luo_global.enabled =3D false; =20 --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3858038AC87 for ; Wed, 3 Jun 2026 15:45:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501505; cv=none; b=pQ5Z7+ZqOSoye9zToP0+xxzwJT3rm2XnwLXtsyQCd3F+wdLPiD0RubgjcDeKIfVcKoEIZtmWw80/5MZ3NWda996PQjqAwVUSgp4QUTSlYyxJURM9ZuAhxBorlLGxReXIQWMWl9AcY6sAo31wiZed6QYDIoqU1+Ck3GZAw/leJRE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501505; c=relaxed/simple; bh=bhQWLj7PPI9UClPVVfb3CJJP1nHiv+tJKCbUyOi+1+A=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bPph2FGGJCfaYQtHIwf/8M0lIY0fo3U5xtc3ghUCXPjw5r5HN2eKT3Qvua9Exh7r9+BlvvYgq9sv9JecvqMBzZ0tAPWpJU2q04kP0K96Atb4WGCF+vPpzhAw53I2XSbD+FCh+R0Szwo2NEeVRp5O9Tz5ycHbfNl4UtLVPxHacE4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=RDnoz0xh; arc=none smtp.client-ip=209.85.222.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="RDnoz0xh" Received: by mail-qk1-f179.google.com with SMTP id af79cd13be357-9158fbaa4bbso97098285a.1 for ; Wed, 03 Jun 2026 08:45:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501503; x=1781106303; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=M0UeBGKKNpBDiXtsHx+XK9ecjuYaKOuvdeJHksP7ylQ=; b=RDnoz0xhdQST67dpD/3XTd3sl734Rd/Q4ixdi8B+7ngVRkJmAZp2RQChXS7t3TmW5I iCjAXP5sVol2Iwf8Ns1k/Pk26qTYrkFNyaUO6LVmW5QJgmJcHVOZzayLpcQoI7HMfqYd hdy1LaFx1qDzF9JLe3+fMFOE+Z9vAEr7NtIr6MnMypeE2jQrpZqmAxEt7QyAZ0M3TN9/ 3wq4uIxXsEnBFWM0JY8e9qtbGOhxs3tHduXVIVoltn1FWzGCmobj73PTocwRkkEIlcTT 66GTCOJLNsxfoGEyPu3BfOlIYkDsX9qSN3Ye+NAGzsZ5BjVdomdVOg/txxOykU53X0X3 LelQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501503; x=1781106303; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=M0UeBGKKNpBDiXtsHx+XK9ecjuYaKOuvdeJHksP7ylQ=; b=osGzeQuOLqDKrM+yY3h0VOz57qB4c5zfon0RgPOiied6u2K1sidzwjrFi+7y4R/i0w z+OKem7nkMn1Ya2DXtCN2lMqbww+bE9FbE41l/joCn/WTFBMZ5P2Cisv9RjY0Jy/iCKu xRyJ+ZF2ofj4N80PvXeZ/dp8qTTqtRwE6HtYP/lryc2Iv7+/H3VEw2p2uWcnEmwRwkKD 6GyZC+8XUAg7E36hAEqMcuTULHYR0Y1lGD1q1hA3TqJ1QhFp539fLEnuKnYkbVSlEFsy hVFToMl0QpkWQ4sWpF08uxWRqpFRGG7HII+Um1DzayXdfSMVN4dcMZPWnl4tq34T7aUo ikxw== X-Forwarded-Encrypted: i=1; AFNElJ+yV3/Q4nkt5Oi/bLNWt8ZFyQsd12uY4eQd6XJJwv4LJGtuvWaFNdH7hot2RAV+JK2Bnd6yIFbRz7ZfBlw=@vger.kernel.org X-Gm-Message-State: AOJu0YzB/9yuCSjaoXiQ9TRHSXjYPxgvl8LcV2XOlwXbDoyyLIOzC7IP CDGOfrBdtiZW31eMbbFWSOVACQfi/QvRdEIA2TkxepfpxW/ILF2v8E1eEjEtsXrXFh8= X-Gm-Gg: Acq92OEhBwesrD09/NKsdCZ6vUBZFXB+mGmTVRrvlrDsBZXDgYByc1XbPuGBarYKD54 bzKOyf36Fq6GLbvhkrlfz742cSt33oDnhRaKBE+TKN9YOR4HVlwGJZ3MWmuPhAdgk+fuGgSibl7 vFBBaOj80ZTo82vlaJWRJAD72SNNwZ4eop76T4syOKiBvVkdOnohRXXnNfq+RWjXmZeIqBrXXLk WiuMXFJKzf871nHxcHK75+s/VaJwtmNcTll35Q6MZN078QKA1yXkl2Rn0fAXWZELdCMXpLJFj+0 eCPF4XzjCNR5T4S4d/spzOu0O9X9gu0r15vGWPTBbB1WM0lgoUFS+yuAIRoXUCTJMBDZDxjlUZt PNQ4lARKc7Gwcp7ozvn/tG2LUcxBPbFYw1CE3dIYykeb+KKjgWjinPxkBNDTPgxhdV5Z5+qSy5R yLCUyRy4Gqc4+AhISZRFrKBqVOuX814Mp+nC0EppQCLJLknNDN99n1b8xU1Bzk4A== X-Received: by 2002:a05:620a:1a09:b0:915:4212:c483 with SMTP id af79cd13be357-9158a7dfdb2mr674935885a.45.1780501503068; Wed, 03 Jun 2026 08:45:03 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a259428sm273352585a.21.2026.06.03.08.45.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:45:02 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 05/13] liveupdate: Extract luo_file_deserialize_one helper Date: Wed, 3 Jun 2026 15:43:54 +0000 Message-ID: <20260603154402.468928-6-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extract the logic for deserializing single entries for files into separate helper functions. In preparation to a linked-block serialization for files. This is a pure code movement, no other changes intended. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- kernel/liveupdate/luo_file.c | 77 ++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c index 208987502f73..9eec07a9e9fc 100644 --- a/kernel/liveupdate/luo_file.c +++ b/kernel/liveupdate/luo_file.c @@ -753,6 +753,46 @@ int luo_file_finish(struct luo_file_set *file_set) return 0; } =20 +static int luo_file_deserialize_one(struct luo_file_set *file_set, + struct luo_file_ser *ser) +{ + struct liveupdate_file_handler *fh; + bool handler_found =3D false; + struct luo_file *luo_file; + + down_read(&luo_register_rwlock); + list_private_for_each_entry(fh, &luo_file_handler_list, list) { + if (!strcmp(fh->compatible, ser->compatible)) { + if (try_module_get(fh->ops->owner)) + handler_found =3D true; + break; + } + } + up_read(&luo_register_rwlock); + + if (!handler_found) { + pr_warn("No registered handler for compatible '%.*s'\n", + (int)sizeof(ser->compatible), + ser->compatible); + return -ENOENT; + } + + luo_file =3D kzalloc_obj(*luo_file); + if (!luo_file) { + module_put(fh->ops->owner); + return -ENOMEM; + } + + luo_file->fh =3D fh; + luo_file->file =3D NULL; + luo_file->serialized_data =3D ser->data; + luo_file->token =3D ser->token; + mutex_init(&luo_file->mutex); + list_add_tail(&luo_file->list, &file_set->files_list); + + return 0; +} + /** * luo_file_deserialize - Reconstructs the list of preserved files in the = new kernel. * @file_set: The incoming file_set to fill with deserialized data. @@ -782,6 +822,7 @@ int luo_file_deserialize(struct luo_file_set *file_set, struct luo_file_set_ser *file_set_ser) { struct luo_file_ser *file_ser; + int err; u64 i; =20 if (!file_set_ser->files) { @@ -809,39 +850,9 @@ int luo_file_deserialize(struct luo_file_set *file_set, */ file_ser =3D file_set->files; for (i =3D 0; i < file_set->count; i++) { - struct liveupdate_file_handler *fh; - bool handler_found =3D false; - struct luo_file *luo_file; - - down_read(&luo_register_rwlock); - list_private_for_each_entry(fh, &luo_file_handler_list, list) { - if (!strcmp(fh->compatible, file_ser[i].compatible)) { - if (try_module_get(fh->ops->owner)) - handler_found =3D true; - break; - } - } - up_read(&luo_register_rwlock); - - if (!handler_found) { - pr_warn("No registered handler for compatible '%.*s'\n", - (int)sizeof(file_ser[i].compatible), - file_ser[i].compatible); - return -ENOENT; - } - - luo_file =3D kzalloc_obj(*luo_file); - if (!luo_file) { - module_put(fh->ops->owner); - return -ENOMEM; - } - - luo_file->fh =3D fh; - luo_file->file =3D NULL; - luo_file->serialized_data =3D file_ser[i].data; - luo_file->token =3D file_ser[i].token; - mutex_init(&luo_file->mutex); - list_add_tail(&luo_file->list, &file_set->files_list); + err =3D luo_file_deserialize_one(file_set, &file_ser[i]); + if (err) + return err; } =20 return 0; --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qk1-f177.google.com (mail-qk1-f177.google.com [209.85.222.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 015063D45FE for ; Wed, 3 Jun 2026 15:45:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501517; cv=none; b=sPc9R+Mv9NJlUa+EoVdqEx2vhGSH7FZ1COIalilnru+3AuhCYaLBSMhRtpRh8vyxf6YhLijY4pc5nk1UfQ4xrEtkkdw0JrMNPxPqvcBrrR+Pz/tLxLZa6tyUrNiDvuoNAZ2APpylw08GM2Wv+8XBDzSF6Lb8UuOHHOW3zfyo7bw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501517; c=relaxed/simple; bh=FlpNYeZf//1t0Q1W/mmEZOxbLRAkN1/PpE/AQRaykXM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p43hwAJp839pgZsHhoU1SGWYkxKfToNHf/ZakpKVfv0fs5JJrw4Ao2RQRB3pLro0tTh4c/ZI4UmV4ZwWpsTOQVnOVd0nM0315JCC9vti8ulGlN5u1dvj74LMrWCGutPvnZ2MuvZo2LfPNVD/MmXkserO24QROhu6mnCw8++fGnU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=fzDH+sWh; arc=none smtp.client-ip=209.85.222.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="fzDH+sWh" Received: by mail-qk1-f177.google.com with SMTP id af79cd13be357-9157b94a07aso253818585a.0 for ; Wed, 03 Jun 2026 08:45:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501515; x=1781106315; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=QfziVgpqRfO53l/kiKYNLloUUY6f9C5CrjqJQDvl8iE=; b=fzDH+sWhPgvP+9rHDU/2d4TTChHdcfZaWMCm7LtaxsfPfIX9xxqsi5NNJz0uqEDQ0e /ORJfyIwmYZpiXusqJ600KPNVJZuJ8oLFQ3tvmzJJzuRnx0WgcE+21/OMyLxRaxedw2g F6I09+mk0Zp2FyZ35tYu/6JbEy+qzcscXbz83SNeweYfalzl0UU6Pqyr7R7vsLFX9oU0 f2x4z1PWvQT/4wX9fbIfO/fmRElPClspLoYTuTx8n+3DinXdm0+uB7q7hf+n3QC2qlTW IXEPCSF8GT3Its5WU8j0hJT5x3Z2ltjETqtq2Wl7y1Tn2ZOnSV1rxkVMAz9k02Bcdei7 nMGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501515; x=1781106315; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=QfziVgpqRfO53l/kiKYNLloUUY6f9C5CrjqJQDvl8iE=; b=GltD4UqG5JFFLVB/kHDi7dpn0okIKN0Q0y6whtji4D5IOWVwt9WHB08NmYpILe2XZw yLm61fTUnC7eIoeYGUSw6x9ZTh77wb6lxaD1RaGtp7feLACDvi1V7mC/yE0os+VIKMqg j8MkFph8JaDABAVpe93H2ZgWxkGlGdx3P7682yM6/GFrR/atJfYwOc3GCyyMokwye5Np OBSDeFzTApVBzMELOgx1XYudKMEYcBJwItl/d6zi0DfeU9KzZEOnnbkyyJ77RQbUWQdD hMxA6mX1sZlbuW6LGFRoaUwAFXVTA3zHejW26fek+JIu7nEeigjAh5wXNPghVfpib2V0 fOzQ== X-Forwarded-Encrypted: i=1; AFNElJ/fJk3NGE+uBMDfDvept9b63BB/NGu8/fqqgUKZwzHQvjWWli4LDAVwdFHF88ve6bnzBuOyjwSQkCGishc=@vger.kernel.org X-Gm-Message-State: AOJu0YyDrqBQtZdO/wFm1ts28yIYxxGD5jM/anM2E2gyRYCwEGYrE6nr Qgd6VS/MXDJB7N3abLRMf+spxD8QHZ0QHcsD+WzeEZrd1m/jdewvEdyqnKH7HKTH7vU= X-Gm-Gg: Acq92OGcg/NeJ1Nh7FW7IurQ0FK4FdrS2nMQYR6hdu5t/hF+Qlq6fQcIRc6HB3vlCFQ QKjMAjBRyQzGmqvpD4SdnFEvJ5zFKD1KRT1hsDNRP/Dk8wCJxzna+Ri1pEHnT/gDvXMxR8ufv2U GsPvaAjQ17Ngu5B2DhSutTL9r33HlGXleYYm0AOofSAZ1X9i54/mzB09uKr/tZ5xvwKopW/jZXe Q+LSSHZbzTJS2F5keJjWc3EpiusfmKjEaCmftnvCOnyyXZfCLPqhGLau7OUPd70qqWM/7QxXyXP 8RLpxP55NOvtmTncd/QBS7JDHjrJzsh8Y7s6/kekeuqMcbx0bBG08TCsjgaC/5zlOEaaHfL9EQJ U87tXNIzb/ZDnwyp82bs3d6IVlpFFIncZdCQRQAKQWlJnqmCnucU3/hWwNHXsXPh6OzhoGi5Nc/ ClTVONAZVSp/iiDMDcsscbyUItzas9lUmXwPUFRUSxGw2c5iNGFNsltxjpbe2uIA== X-Received: by 2002:a05:620a:2406:10b0:915:6c4d:d74b with SMTP id af79cd13be357-9158a7aa7d7mr477899185a.31.1780501514839; Wed, 03 Jun 2026 08:45:14 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a237330sm280242385a.16.2026.06.03.08.45.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:45:14 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 06/13] liveupdate: Extract luo_session_deserialize_one helper Date: Wed, 3 Jun 2026 15:43:55 +0000 Message-ID: <20260603154402.468928-7-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extract the logic for deserializing single entries for sessions into separate helper functions. In preparation to a linked-block serialization for sessions. This is a pure code movement, no other changes intended. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- kernel/liveupdate/luo_session.c | 63 +++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index 85782c6f3d6c..1cd315e0f6de 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -555,6 +555,40 @@ int __init luo_session_setup_incoming(u64 sessions_pa) return 0; } =20 +static int luo_session_deserialize_one(struct luo_session_header *sh, + struct luo_session_ser *ser) +{ + struct luo_session *session; + int err; + + session =3D luo_session_alloc(ser->name); + if (IS_ERR(session)) { + pr_warn("Failed to allocate session [%.*s] during deserialization %pe\n", + (int)sizeof(ser->name), ser->name, session); + return PTR_ERR(session); + } + + err =3D luo_session_insert(sh, session); + if (err) { + pr_warn("Failed to insert session [%s] %pe\n", + session->name, ERR_PTR(err)); + luo_session_free(session); + return err; + } + + scoped_guard(mutex, &session->mutex) { + err =3D luo_file_deserialize(&session->file_set, + &ser->file_set_ser); + } + if (err) { + pr_warn("Failed to deserialize files for session [%s] %pe\n", + session->name, ERR_PTR(err)); + return err; + } + + return 0; +} + int luo_session_deserialize(void) { struct luo_session_header *sh =3D &luo_session_global.incoming; @@ -586,34 +620,9 @@ int luo_session_deserialize(void) * reliably reset devices and reclaim memory. */ for (int i =3D 0; i < sh->header_ser->count; i++) { - struct luo_session *session; - - session =3D luo_session_alloc(sh->ser[i].name); - if (IS_ERR(session)) { - pr_warn("Failed to allocate session [%.*s] during deserialization %pe\n= ", - (int)sizeof(sh->ser[i].name), - sh->ser[i].name, session); - err =3D PTR_ERR(session); - goto save_err; - } - - err =3D luo_session_insert(sh, session); - if (err) { - pr_warn("Failed to insert session [%s] %pe\n", - session->name, ERR_PTR(err)); - luo_session_free(session); - goto save_err; - } - - scoped_guard(mutex, &session->mutex) { - err =3D luo_file_deserialize(&session->file_set, - &sh->ser[i].file_set_ser); - } - if (err) { - pr_warn("Failed to deserialize files for session [%s] %pe\n", - session->name, ERR_PTR(err)); + err =3D luo_session_deserialize_one(sh, &sh->ser[i]); + if (err) goto save_err; - } } =20 kho_restore_free(sh->header_ser); --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qv1-f41.google.com (mail-qv1-f41.google.com [209.85.219.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 428BE3D34A2 for ; Wed, 3 Jun 2026 15:45:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501530; cv=none; b=Q/nLn7wG4gdA2t7TJ6vFjEMX6Vzd/6h9D+/qTigNgjAYfp/Hmz3TBYI4Zyc8qb48XIaQoExr83iCb7+AZnU0acCthbrz6ZQ3mbMJqKR+FxVL/48kapfV59+SSVYcoiM2vnQeda2AZsmV8WmJZWIURZdUSmvroV2/emf2gQnVXjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501530; c=relaxed/simple; bh=Rqw44ONYhpmAMUMH/10ptSTwhzIjA6CaKCf/ZcuuBQw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HLzBSjwCAj0asCYQG+D4zYPmEAmic16K8FrnvAq/LDLlK+O4t4ysLsPrCPwlx5D5ua0R0s0u1FD5/hPhb2tbHEnvlBTNdsySY5+Wz+kSvYB1NDXT5DtA5tYn4cYFpN2PC4VPPnEW0Qlb+/sMzfcHeaC+RbCU8cKt+cxZ4ZebqEI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=dV8IIthR; arc=none smtp.client-ip=209.85.219.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="dV8IIthR" Received: by mail-qv1-f41.google.com with SMTP id 6a1803df08f44-8ccef25789fso35396246d6.3 for ; Wed, 03 Jun 2026 08:45:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501527; x=1781106327; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=d4aSCoL41048YLbu/Ppdp+fUB4uFMSQf0r9BjBD04lw=; b=dV8IIthRFIgw7vTm8q173kCneSY53fPAKf97+L0p/gQoBfs/vIhALx2kXMM9wbUW9B 2Q2ZgtN8SedCCzWGVyZG9cDWhUw1MjLsB6r6gsTnHS9WjFzW69JjXNoa4IVCQOvGenAh mS3tOMrHKJv2BSUikESOsiBxqy19T0OHpjOZpNeyXVSU6YfrVvBg/DBtV9m6kbM9LEAN rllnoUr7DfJv+Y8I1vfV8Gaxn+ZThB8xH7RDsjkb19Nip6Wlq0Zw+wneDBgUcHQJdObi PKa+GSPnJcmJmsQtrQpeMUAM46Q3HQF4CGSmiAd46/P3tZRSWOkematbV+g34Z4Ha0aI jUrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501527; x=1781106327; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=d4aSCoL41048YLbu/Ppdp+fUB4uFMSQf0r9BjBD04lw=; b=BAn7U60ZzN+nSZtelp4ixXtilEy+PaVoK4PAH2opiU+KtqIGqLmQ628fMef/NcO0Dd ANkUJqU0G0YHhHcFyzK87D4tf+TkHk75O1gf42SDTWD5/eQk5mAn+cPxA+OyNnguLh+0 N4qVParfXBWYDvOselz55DQswIxMeQdGvQcD/g8jyVTmCAPlyKTq6xHnBr0VNtPRJfMw 5fwFV/WPqRzvrIOS6yRhhPbe5g2vet4759sGGmxhXrPmBKprbW3cN9lGlxduiMkHomnn k7/7E2TMpIWmUYctd/1ps8XleCPke9MicUtJ1F+69mdUa2ATWxdZGcVE3PmebBPQu2j4 EBOQ== X-Forwarded-Encrypted: i=1; AFNElJ+E3XKcebcXd9E/C1ukT8a/sfWpQxmkt91mfF6OOaQLSgRjWy212RQn6KVv+e+hpoe79Quh3ksGehj0rTE=@vger.kernel.org X-Gm-Message-State: AOJu0Ywbbh37bDXH6vXbLcgmjVS8MMKllV8k1aynfniuuPGToNct2X9P Uxeg5RoQFNughJ4Iyk+WBxin4T8O8qCYThpfoBEEmJFG5LRNMjf4lTjH0SeRqTMkDwI= X-Gm-Gg: Acq92OEPCPqnLOpbBD8+4xvXY+KNgvvmesasLUZ/hxhSAw6pA58EeYL062vd0KZ2JWG YGpUWlpVfUtcB7yROjq3VdRa/ej4W19CDr9bOZG4JdkjLM6vdwJi/5PKJLMy3Z61EmqetjBmNQo hDygQUHtS1jDoqbKITKWBCBtDBQTAoBEZe1kLlS2Zsv0cMbwndGU7/UnUvHFIOVXs7Pb2habGKG gzMCiB4FVhF4olQRa/gc2Qx3cJqTHi83J011jbYrB+3BRAoKHM7s7HovM6j9h/xRXf98QZEDL+L 0+Fx94VFeqhMT6p3lQtsvo/D14e4UaJ02I+DV2PKd+xKWkqHoQ9b4TbmodHjHfyvJiAc5quEGMk Pc7LIaukfri2O7MEqucXj4WeIGRb8+qYUEU+N3xbNfKehvcPWV9SWO1uyVCROMcp2MXSG7WRmDQ FAmM2z7TE5DXTiSySD/RVDXTiBLH8NYdloTzR1rQsaKYE8NpBIvqoI8QvwFZlYuQ== X-Received: by 2002:a05:6214:488b:b0:8b3:f911:c1df with SMTP id 6a1803df08f44-8cecdea195cmr39593016d6.21.1780501526838; Wed, 03 Jun 2026 08:45:26 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8ceccd9fc7dsm23519496d6.5.2026.06.03.08.45.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:45:26 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 07/13] kho: add support for linked-block serialization Date: Wed, 3 Jun 2026 15:43:56 +0000 Message-ID: <20260603154402.468928-8-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a linked-block serialization mechanism for state handover. Previously, LUO used contiguous memory blocks for serializing sessions and files, which imposed limits on the total number of items that could be preserved across a live update. This commit adds the infrastructure for a more flexible, block-based approach where serialized data is stored in a chain of linked blocks. This is a generic KHO serialization block infrastructure that can be used by multiple subsystems. Signed-off-by: Pasha Tatashin --- Documentation/core-api/kho/abi.rst | 5 + Documentation/core-api/kho/index.rst | 11 + MAINTAINERS | 1 + include/linux/kho/abi/block.h | 54 ++++ include/linux/kho/abi/kexec_handover.h | 2 +- include/linux/kho_block.h | 106 +++++++ kernel/liveupdate/Makefile | 1 + kernel/liveupdate/kho_block.c | 416 +++++++++++++++++++++++++ 8 files changed, 595 insertions(+), 1 deletion(-) create mode 100644 include/linux/kho/abi/block.h create mode 100644 include/linux/kho_block.h create mode 100644 kernel/liveupdate/kho_block.c diff --git a/Documentation/core-api/kho/abi.rst b/Documentation/core-api/kh= o/abi.rst index 799d743105a6..edeb5b311963 100644 --- a/Documentation/core-api/kho/abi.rst +++ b/Documentation/core-api/kho/abi.rst @@ -28,6 +28,11 @@ KHO persistent memory tracker ABI .. kernel-doc:: include/linux/kho/abi/kexec_handover.h :doc: KHO persistent memory tracker =20 +KHO serialization block ABI +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + +.. kernel-doc:: include/linux/kho/abi/block.h + See Also =3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/Documentation/core-api/kho/index.rst b/Documentation/core-api/= kho/index.rst index 0a2dee4f8e7d..320914a42178 100644 --- a/Documentation/core-api/kho/index.rst +++ b/Documentation/core-api/kho/index.rst @@ -83,6 +83,17 @@ Public API .. kernel-doc:: kernel/liveupdate/kexec_handover.c :export: =20 +KHO Serialization Blocks API +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + +.. kernel-doc:: kernel/liveupdate/kho_block.c + :doc: KHO Serialization Blocks + +.. kernel-doc:: include/linux/kho_block.h + +.. kernel-doc:: kernel/liveupdate/kho_block.c + :internal: + See Also =3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/MAINTAINERS b/MAINTAINERS index 9ec290e38b44..920ba7622afa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14208,6 +14208,7 @@ F: Documentation/admin-guide/mm/kho.rst F: Documentation/core-api/kho/* F: include/linux/kexec_handover.h F: include/linux/kho/ +F: include/linux/kho_block.h F: kernel/liveupdate/kexec_handover* F: lib/test_kho.c F: tools/testing/selftests/kho/ diff --git a/include/linux/kho/abi/block.h b/include/linux/kho/abi/block.h new file mode 100644 index 000000000000..d06d64b963be --- /dev/null +++ b/include/linux/kho/abi/block.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2026, Google LLC. + * Pasha Tatashin + */ + +/** + * DOC: KHO Serialization Blocks ABI + * + * Subsystems using the KHO Serialization Blocks framework rely on the sta= ble + * Application Binary Interface defined below to pass serialized state fro= m a + * pre-update kernel to a post-update kernel. + * + * This interface is a contract. Any modification to the structure fields, + * compatible strings, or the layout of the `__packed` serialization + * structures defined here constitutes a breaking change. Such changes req= uire + * incrementing the version number in the `KHO_FDT_COMPATIBLE` string to + * prevent a new kernel from misinterpreting data from an old kernel. + * + * Changes are allowed provided the compatibility version is incremented; + * however, backward/forward compatibility is only guaranteed for kernels + * supporting the same ABI version. + */ + +#ifndef _LINUX_KHO_ABI_BLOCK_H +#define _LINUX_KHO_ABI_BLOCK_H + +#include +#include + +/** + * KHO_BLOCK_SIZE - The size of each serialization block. + * + * This is defined as PAGE_SIZE. PAGE_SIZE is ABI compliant because live + * update between kernels with different page sizes is not supported by KH= O. + */ +#define KHO_BLOCK_SIZE PAGE_SIZE + +/** + * struct kho_block_header_ser - Header for the serialized data block. + * @next: Physical address of the next struct kho_block_header_ser. + * @count: The number of entries that immediately follow this header in the + * memory block. + * + * This structure is located at the beginning of a block of physical memory + * preserved across a kexec. It provides the necessary metadata to interpr= et + * the array of entries that follow. + */ +struct kho_block_header_ser { + u64 next; + u64 count; +} __packed; + +#endif /* _LINUX_KHO_ABI_BLOCK_H */ diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi= /kexec_handover.h index fb2d37417ad9..5e2eb8519bda 100644 --- a/include/linux/kho/abi/kexec_handover.h +++ b/include/linux/kho/abi/kexec_handover.h @@ -90,7 +90,7 @@ */ =20 /* The compatible string for the KHO FDT root node. */ -#define KHO_FDT_COMPATIBLE "kho-v3" +#define KHO_FDT_COMPATIBLE "kho-v4" =20 /* The FDT property for the preserved memory map. */ #define KHO_FDT_MEMORY_MAP_PROP_NAME "preserved-memory-map" diff --git a/include/linux/kho_block.h b/include/linux/kho_block.h new file mode 100644 index 000000000000..93a7cc2be5f5 --- /dev/null +++ b/include/linux/kho_block.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2026, Google LLC. + * Pasha Tatashin + */ + +#ifndef _LINUX_KHO_BLOCK_H +#define _LINUX_KHO_BLOCK_H + +#include +#include +#include + +/** + * struct kho_block - Internal representation of a serialization block. + * @list: List head for linking blocks in memory. + * @ser: Pointer to the serialized header in preserved memory. + */ +struct kho_block { + struct list_head list; + struct kho_block_header_ser *ser; +}; + +/** + * struct kho_block_set - A set of blocks containing serialized entries of= the same type. + * @blocks: The list of serialization blocks (struct kho_block). + * @nblocks: The number of allocated serialization blocks. + * @head_pa: Physical address of the first block header. + * @entry_size: The size of each entry in the blocks. + * @count_per_block: The maximum number of entries each block can hold. + * @incoming: True if this block set was restored from the previous= kernel. + * + * Note: Synchronization and locking are the responsibility of the caller. + * The block set structure itself is not internally synchronized. + */ +struct kho_block_set { + struct list_head blocks; + long nblocks; + u64 head_pa; + size_t entry_size; + u64 count_per_block; + bool incoming; +}; + +/** + * struct kho_block_set_it - Iterator for serializing entries into blocks. + * @bs: The block set being iterated. + * @block: The current block. + * @i: The current entry index within @block. + */ +struct kho_block_set_it { + struct kho_block_set *bs; + struct kho_block *block; + u64 i; +}; + +/** + * KHO_BLOCK_SET_INIT - Initialize a static kho_block_set. + * @_name: Name of the kho_block_set variable. + * @_entry_size: The size of each entry in the block set. + */ +#define KHO_BLOCK_SET_INIT(_name, _entry_size) { \ + .blocks =3D LIST_HEAD_INIT((_name).blocks), \ + .entry_size =3D _entry_size, \ + .count_per_block =3D (KHO_BLOCK_SIZE - \ + sizeof(struct kho_block_header_ser)) / \ + (_entry_size), \ +} + +void kho_block_set_init(struct kho_block_set *bs, size_t entry_size); + +int kho_block_set_grow(struct kho_block_set *bs, u64 count); +void kho_block_set_shrink(struct kho_block_set *bs, u64 count); + +int kho_block_set_restore(struct kho_block_set *bs, u64 head_pa); +void kho_block_set_destroy(struct kho_block_set *bs); +void kho_block_set_clear(struct kho_block_set *bs); + +/** + * kho_block_set_head_pa - Get the physical address of the first block hea= der. + * @bs: The block set. + * + * Return: The physical address of the first block header, or 0 if empty. + */ +static inline u64 kho_block_set_head_pa(struct kho_block_set *bs) +{ + return bs->head_pa; +} + +/** + * kho_block_set_is_empty - Check if the block set has no allocated blocks. + * @bs: The block set. + * + * Return: True if there are no blocks in the set, false otherwise. + */ +static inline bool kho_block_set_is_empty(struct kho_block_set *bs) +{ + return list_empty(&bs->blocks); +} + +void kho_block_set_it_init(struct kho_block_set_it *it, struct kho_block_s= et *bs); +void *kho_block_set_it_reserve_entry(struct kho_block_set_it *it); +void *kho_block_set_it_read_entry(struct kho_block_set_it *it); +void *kho_block_set_it_prev(struct kho_block_set_it *it); + +#endif /* _LINUX_KHO_BLOCK_H */ diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile index d2f779cbe279..eec9d3ae07eb 100644 --- a/kernel/liveupdate/Makefile +++ b/kernel/liveupdate/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 =20 luo-y :=3D \ + kho_block.o \ luo_core.o \ luo_file.o \ luo_flb.o \ diff --git a/kernel/liveupdate/kho_block.c b/kernel/liveupdate/kho_block.c new file mode 100644 index 000000000000..0d2a342ef422 --- /dev/null +++ b/kernel/liveupdate/kho_block.c @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (c) 2026, Google LLC. + * Pasha Tatashin + */ + +/** + * DOC: KHO Serialization Blocks + * + * KHO provides a mechanism to preserve stateful data across a kexec hando= ver + * by serializing it into memory blocks, and provides the common + * infrastructure for managing these blocks. + * + * Each block consists of a header (struct kho_block_header_ser) followed = by an + * array of serialized entries. Multiple blocks are linked together via a + * physical pointer in the header, forming a linked list that can be easily + * traversed in both the current and the next kernel. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +/* + * Safeguard limit for the number of serialization blocks. This is used to + * prevent infinite loops and excessive memory allocation in case of memory + * corruption in the preserved state. + * + * With a 4KB page size, 10k blocks is about 40MB. For 32-byte entries + * (e.g. 4 u64s), each block holds up to 127 entries (accounting for the + * 16-byte header), allowing the block set to hold up to 1.27M entries. + */ +#define KHO_MAX_BLOCKS 10000 + +/** + * kho_block_set_init - Initialize a block set. + * @bs: The block set to initialize. + * @entry_size: The size of each entry in the blocks. + */ +void kho_block_set_init(struct kho_block_set *bs, size_t entry_size) +{ + *bs =3D (struct kho_block_set)KHO_BLOCK_SET_INIT(*bs, entry_size); + WARN_ON_ONCE(!bs->count_per_block); +} + +/* Serialized entries start immediately after the block header */ +static void *kho_block_entries(struct kho_block *block) +{ + return (void *)(block->ser + 1); +} + +/* Get the address of the serialized entry at the specified index */ +static void *kho_block_entry(struct kho_block_set_it *it, u64 index) +{ + return kho_block_entries(it->block) + (index * it->bs->entry_size); +} + +/* Free serialized data */ +static void kho_block_free_ser(struct kho_block_set *bs, + struct kho_block_header_ser *ser) +{ + if (bs->incoming) + kho_restore_free(ser); + else + kho_unpreserve_free(ser); +} + +static struct kho_block_header_ser *kho_block_alloc_ser(struct kho_block_s= et *bs) +{ + WARN_ON_ONCE(bs->incoming); + return kho_alloc_preserve(KHO_BLOCK_SIZE); +} + +static int kho_block_add(struct kho_block_set *bs, + struct kho_block_header_ser *ser) +{ + struct kho_block *block, *last; + + if (bs->nblocks >=3D KHO_MAX_BLOCKS) + return -ENOSPC; + + block =3D kzalloc_obj(*block); + if (!block) + return -ENOMEM; + + block->ser =3D ser; + last =3D list_last_entry_or_null(&bs->blocks, struct kho_block, list); + list_add_tail(&block->list, &bs->blocks); + bs->nblocks++; + + if (last) + last->ser->next =3D virt_to_phys(ser); + else + bs->head_pa =3D virt_to_phys(ser); + + return 0; +} + +static int kho_block_set_grow_one(struct kho_block_set *bs) +{ + struct kho_block_header_ser *ser; + int err; + + ser =3D kho_block_alloc_ser(bs); + if (IS_ERR(ser)) + return PTR_ERR(ser); + + err =3D kho_block_add(bs, ser); + if (err) { + kho_block_free_ser(bs, ser); + return err; + } + + return 0; +} + +static void kho_block_set_shrink_one(struct kho_block_set *bs) +{ + struct kho_block *last, *new_last; + + if (list_empty(&bs->blocks)) + return; + + last =3D list_last_entry(&bs->blocks, struct kho_block, list); + list_del(&last->list); + bs->nblocks--; + kho_block_free_ser(bs, last->ser); + kfree(last); + + new_last =3D list_last_entry_or_null(&bs->blocks, struct kho_block, list); + if (new_last) + new_last->ser->next =3D 0; + else + bs->head_pa =3D 0; +} + +/** + * kho_block_set_grow - Expand the block set to accommodate the target cou= nt. + * @bs: The block set. + * @count: The target number of valid entries to accommodate. + * + * Dynamically preallocates and links preserved memory blocks if the target + * entry count exceeds the current total capacity of the set, ensuring they + * are available during serialization/deserialization. + * + * Context: Caller must hold a lock protecting the block set. + * Return: 0 on success, or a negative errno on failure. + */ +int kho_block_set_grow(struct kho_block_set *bs, u64 count) +{ + long orig_nblocks =3D bs->nblocks; + int err; + + if (WARN_ON_ONCE(bs->incoming)) + return -EINVAL; + + while (count > bs->nblocks * bs->count_per_block) { + err =3D kho_block_set_grow_one(bs); + if (err) + goto err_shrink; + } + + return 0; + +err_shrink: + while (bs->nblocks > orig_nblocks) + kho_block_set_shrink_one(bs); + return err; +} + +/** + * kho_block_set_shrink - Shrink the block set to accommodate the target c= ount. + * @bs: The block set. + * @count: The target number of valid entries to accommodate. + * + * Releases and unallocates redundant preserved memory blocks. Checks if t= he + * last block in the set can be removed because the remaining entry count = is + * fully accommodated by the preceding blocks. + * + * Note: It is the caller's responsibility to ensure that entries are remo= ved + * in the reverse order of their insertion. Because shrinking destroys the= last + * block in the set, removing entries in any other order would corrupt act= ive + * data. + * + * Context: Caller must hold a lock protecting the block set. + */ +void kho_block_set_shrink(struct kho_block_set *bs, u64 count) +{ + while (bs->nblocks > 0 && count <=3D (bs->nblocks - 1) * bs->count_per_bl= ock) + kho_block_set_shrink_one(bs); +} + +/* + * kho_block_set_is_cyclic - Check for cycles in a linked list of blocks. + * Uses Floyd's cycle-finding algorithm to ensure sanity of the incoming l= ist. + * + * Return: true if a cycle or corruption is detected, false otherwise. + */ +static bool kho_block_set_is_cyclic(struct kho_block_set *bs) +{ + struct kho_block_header_ser *fast; + struct kho_block_header_ser *slow; + int count =3D 0; + + fast =3D phys_to_virt(bs->head_pa); + slow =3D fast; + + while (fast) { + if (count++ >=3D KHO_MAX_BLOCKS) { + pr_err("Block set is corrupted\n"); + return true; + } + + if (!fast->next) + break; + + fast =3D phys_to_virt(fast->next); + if (!fast->next) + break; + + fast =3D phys_to_virt(fast->next); + slow =3D phys_to_virt(slow->next); + + if (slow =3D=3D fast) { + pr_err("Block set is corrupted\n"); + return true; + } + } + + return false; +} + +/** + * kho_block_set_restore - Restore a block set from a physical address. + * @bs: The block set to restore. + * @head_pa: Physical address of the first block header. + * + * Restores a serialized block set from a given physical address. The call= er is + * responsible for ensuring that the block set @bs has been allocated and + * initialized prior to calling this function. + * + * Return: 0 on success, or a negative errno on failure. + */ +int kho_block_set_restore(struct kho_block_set *bs, u64 head_pa) +{ + struct kho_block_header_ser *ser; + u64 next_pa =3D head_pa; + int err; + + /* Restored block sets use size from the previous kernel */ + bs->incoming =3D true; + if (!head_pa) + return 0; + + bs->head_pa =3D head_pa; + if (kho_block_set_is_cyclic(bs)) { + bs->head_pa =3D 0; + return -EINVAL; + } + + while (next_pa) { + ser =3D phys_to_virt(next_pa); + if (!ser->count || ser->count > bs->count_per_block) { + pr_warn("Block contains invalid entry count: %llu\n", + ser->count); + err =3D -EINVAL; + goto err_destroy; + } + err =3D kho_block_add(bs, ser); + if (err) + goto err_destroy; + next_pa =3D ser->next; + } + + return 0; + +err_destroy: + kho_block_set_destroy(bs); + + /* Free the remaining un-restored blocks in the physical chain */ + while (next_pa) { + struct kho_block_header_ser *next_ser =3D phys_to_virt(next_pa); + + next_pa =3D next_ser->next; + kho_block_free_ser(bs, next_ser); + } + return err; +} + +/** + * kho_block_set_destroy - Destroy all blocks in a block set. + * @bs: The block set. + */ +void kho_block_set_destroy(struct kho_block_set *bs) +{ + struct kho_block *block, *tmp; + + list_for_each_entry_safe(block, tmp, &bs->blocks, list) { + list_del(&block->list); + kho_block_free_ser(bs, block->ser); + kfree(block); + } + bs->nblocks =3D 0; + bs->head_pa =3D 0; +} + +/** + * kho_block_set_clear - Clear all serialized data in a block set. + * @bs: The block set to clear. + */ +void kho_block_set_clear(struct kho_block_set *bs) +{ + struct kho_block *block; + + list_for_each_entry(block, &bs->blocks, list) { + block->ser->count =3D 0; + memset(block->ser + 1, 0, KHO_BLOCK_SIZE - sizeof(*block->ser)); + } +} + +/** + * kho_block_set_it_init - Initialize a block set iterator. + * @it: The iterator to initialize. + * @bs: The block set to iterate over. + */ +void kho_block_set_it_init(struct kho_block_set_it *it, struct kho_block_s= et *bs) +{ + it->bs =3D bs; + it->block =3D list_first_entry_or_null(&bs->blocks, struct kho_block, lis= t); + it->i =3D 0; +} + +/** + * kho_block_set_it_reserve_entry - Reserve and return the next available = slot for writing. + * @it: The block iterator. + * + * Reserves a slot in the current block during state serialization to add = a new + * entry, advancing the internal index. If the current block is full, it + * automatically moves to the next block in the set. + * + * Return: A pointer to the reserved entry slot, or NULL if the block set's + * capacity is fully exhausted. + */ +void *kho_block_set_it_reserve_entry(struct kho_block_set_it *it) +{ + void *entry; + + if (!it->block) + return NULL; + + if (it->i =3D=3D it->bs->count_per_block) { + if (list_is_last(&it->block->list, &it->bs->blocks)) + return NULL; + it->block =3D list_next_entry(it->block, list); + it->i =3D 0; + } + + entry =3D kho_block_entry(it, it->i++); + it->block->ser->count =3D it->i; + return entry; +} + +/** + * kho_block_set_it_read_entry - Read the next serialized entry from the b= lock set. + * @it: The block iterator. + * + * Iterates through previously written entries during state deserializatio= n, + * respecting the actual count stored in each block's header. + * + * Return: A pointer to the next serialized entry, or NULL if all serializ= ed + * entries have been read. + */ +void *kho_block_set_it_read_entry(struct kho_block_set_it *it) +{ + if (!it->block) + return NULL; + + if (it->i =3D=3D it->block->ser->count) { + if (list_is_last(&it->block->list, &it->bs->blocks)) + return NULL; + it->block =3D list_next_entry(it->block, list); + it->i =3D 0; + } + + return kho_block_entry(it, it->i++); +} + +/** + * kho_block_set_it_prev - Return the previous entry slot in the block set. + * @it: The block iterator. + * + * If the current index is at the start of a block, it automatically moves= to + * the end of the previous block. + * + * Return: A pointer to the previous entry slot, or NULL if at the very + * beginning of the block set. + */ +void *kho_block_set_it_prev(struct kho_block_set_it *it) +{ + if (!it->block) + return NULL; + + if (it->i =3D=3D 0) { + if (list_is_first(&it->block->list, &it->bs->blocks)) + return NULL; + it->block =3D list_prev_entry(it->block, list); + it->i =3D it->bs->count_per_block; + } + + return kho_block_entry(it, --it->i); +} --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qk1-f175.google.com (mail-qk1-f175.google.com [209.85.222.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E6FC3D6CAE for ; Wed, 3 Jun 2026 15:45:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501554; cv=none; b=BD0GSBD3g7+Hd4WL5uByPb4wfA53njOWN63ziYfLoPe99Uen6u2goBl2GyaeZikwEvGilfOHqxo3lq5/IOkyi/IX5uPTE6iiXUDr0w3wWfdU6FCfKGU3FLIoTFIfVcWuieX30hDiBpxSfLFMl2a2fZvI0nla8tqPULMEqOPCm8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501554; c=relaxed/simple; bh=BUqck5wg4D12YPrDF5xhx84BkumRp2TDeBPRt9od/wk=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OqFkeR7TqIRJk45zUnUyLu/sCXh8ma77ECtOjxDdNOEEQ7S1Qtn4XLhefIv1z75qKg6r3jsgUAMh6u0pGcIVbpCdokY+xngor8r9TbPzVsftnASxwB3BX3Pa6v0CRMFGvLR11w6rYD+MjJjgeRNDqm3dGW114xVbcpSVy3nPzzM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=I4YDE9wI; arc=none smtp.client-ip=209.85.222.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="I4YDE9wI" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-9157b949fc7so247110985a.3 for ; Wed, 03 Jun 2026 08:45:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501550; x=1781106350; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=C9xWUzUEP3GatCDCPhqDCyXoyiDq9Ol5847oPRS2f7E=; b=I4YDE9wI9iukxF1Ud3R0+jl3JtmXaczftHC59RZZfaSXuM3zrXPdhfTD3IOhtnik4s FkgH506gp/tbSvRsAT0rf+oH2kp+a4U3OPrTL1Da75hvIEYNb3YxUNAMLVRvLFnHerLU 3Q1bRJSO8LWWNjRfsZN0qHHFW/zlJTWfuzXpf/1LIaZvFnucwkT1m34nGX8oPfyAQUI+ LADPzqj6iV7mj2O/DoWwNNNjcSRp7EDE7hqU+eP2H8ub++CacRtQ6ymDZlIQN5LTLDf8 BWba5WuHBgfS3sHmoA2GbL40cF6UybKukar9wNZKat1Di6HiHGYQIQnBqOnHnyflbZMN 5eSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501550; x=1781106350; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=C9xWUzUEP3GatCDCPhqDCyXoyiDq9Ol5847oPRS2f7E=; b=B/AzyhdVU3RNvaPYjSiEm9GRLDCr/ZfFnzKec2U4uAxrJLrMNbp1HlJFA+rCdnIKqO jaNOCPbRmqU1pDHu6om60NxgxQ7qaZpt5HkofpOZ6V7ymoy88bqg4M4GH1OKeyIWVFi+ aYc7z++ocMTAv0WX6mGJUCyw8aEVGRIs7T3SAB9TjEOyhAITUSyxjdmxL2NXQV4C1WSh d2UZRXndBnjsLu0uNqxoAg4/QJEg6FheuDJXt7tIlSgdWVdQkeX+rz6naOePQF3EXkcp JL9yXrLVemkHjZSx0GOn6OlXYRbqd05cuyrMHShdXEwYeHd+xiJLNWdF2hT4uoAymwQe x8cg== X-Forwarded-Encrypted: i=1; AFNElJ9kbACCGET457W4bQqLZ63q9PEILG9n0S3hWnvDdP8DN1OlPxFad8l33CNy2Ix+VfBNd0dw4MwJ/xaTssc=@vger.kernel.org X-Gm-Message-State: AOJu0YydFHBtd2kcVQyqCG42scQeHEhGp2EW2J8b8sF3/4kq3oOYBlri xXOGfq/XBo1ULllhzyGqMJZS0JFCZqUJdhMyL2Px/ouRC1QN+10Cmimc87aly3bsITM= X-Gm-Gg: Acq92OE2xukswpxlFhEUFUhexoF1sCy/+fGG53jx6ueHP4f5fcelhFxzT1aOgrjR/gO 4aOoSi/SQzE9iwSzeX5hx9Ld8l9XBZ30m0HQuickM9n67peUz699j1smGhXuTdQB5d1rYRNE5wu WJnRS7yzMurRxcfsPBlakHG3Nd6xkHgfWpq01QFlqsEm5/DNR8Yi+EdI6K9wjipVV/lk00KdgCo xS/Djil+QJGJBfMMdp32aBNiRa/eM2ObcFb0xAhWjFyNgejWigtx9rXUfsKhyZACrcT1pTTn380 Q/5PMXQfGCee6K9hsLuvVz2DXHQ8jRpCso/3FdE5h7ZfUbM/HNUAMyT7gcAW954bFRlaexs57fy Qwfvcs+agmrypzt6NCv2rAkzcB9Ae1yA44930wu7CJB1RohX+Ug+zzLNduBoA+0IyfFBvatesub SC8jboMZieWUSonu6Nqj2YtP3QyGKArtxSWhfgGu3dE4RMgDwFZ9m4fGHWPTBB+A== X-Received: by 2002:a05:620a:25cf:b0:90d:b6b7:caa2 with SMTP id af79cd13be357-9158a64528cmr652914085a.11.1780501538664; Wed, 03 Jun 2026 08:45:38 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a00ba04sm272435585a.7.2026.06.03.08.45.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:45:38 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 08/13] liveupdate: defer session block allocation and physical address setting Date: Wed, 3 Jun 2026 15:43:57 +0000 Message-ID: <20260603154402.468928-9-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, luo_session_setup_outgoing() allocates the session block and sets its physical address in the header immediately. With upcoming dynamic block-based session management, this makes the first block different from the rest. Move the allocation to where it is first needed. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- kernel/liveupdate/luo_core.c | 4 +- kernel/liveupdate/luo_internal.h | 2 +- kernel/liveupdate/luo_session.c | 68 ++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 69b00e7d0f8f..1b2bda22902d 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -165,9 +165,7 @@ static int __init luo_state_setup(void) strscpy(luo_ser->compatible, LUO_ABI_COMPATIBLE, sizeof(luo_ser->compatib= le)); luo_ser->liveupdate_num =3D luo_global.liveupdate_num + 1; =20 - err =3D luo_session_setup_outgoing(&luo_ser->sessions_pa); - if (err) - goto exit_free_luo_ser; + luo_session_setup_outgoing(&luo_ser->sessions_pa); =20 err =3D luo_flb_setup_outgoing(&luo_ser->flbs_pa); if (err) diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_inter= nal.h index fe22086bfbeb..ee18f9a11b91 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -79,7 +79,7 @@ extern struct rw_semaphore luo_register_rwlock; =20 int luo_session_create(const char *name, struct file **filep); int luo_session_retrieve(const char *name, struct file **filep); -int __init luo_session_setup_outgoing(u64 *sessions_pa); +void __init luo_session_setup_outgoing(u64 *sessions_pa); int __init luo_session_setup_incoming(u64 sessions_pa); int luo_session_serialize(void); int luo_session_deserialize(void); diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index 1cd315e0f6de..2411849a34e3 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -108,15 +108,16 @@ static DECLARE_RWSEM(luo_session_serialize_rwsem); =20 /** * struct luo_session_header - Header struct for managing LUO sessions. - * @count: The number of sessions currently tracked in the @list. - * @list: The head of the linked list of `struct luo_session` instan= ces. - * @rwsem: A read-write semaphore providing synchronized access to the - * session list and other fields in this structure. - * @header_ser: The header data of serialization array. - * @ser: The serialized session data (an array of - * `struct luo_session_ser`). - * @active: Set to true when first initialized. If previous kernel did= not - * send session data, active stays false for incoming. + * @count: The number of sessions currently tracked in the @list. + * @list: The head of the linked list of `struct luo_session` insta= nces. + * @rwsem: A read-write semaphore providing synchronized access to t= he + * session list and other fields in this structure. + * @header_ser: The header data of serialization array. + * @ser: The serialized session data (an array of + * `struct luo_session_ser`). + * @sessions_pa: Points to the location of sessions_pa within struct luo_s= er. + * @active: Set to true when first initialized. If previous kernel di= d not + * send session data, active stays false for incoming. */ struct luo_session_header { long count; @@ -124,6 +125,7 @@ struct luo_session_header { struct rw_semaphore rwsem; struct luo_session_header_ser *header_ser; struct luo_session_ser *ser; + u64 *sessions_pa; bool active; }; =20 @@ -171,10 +173,30 @@ static void luo_session_free(struct luo_session *sess= ion) kfree(session); } =20 +static int luo_session_grow_ser(struct luo_session_header *sh) +{ + struct luo_session_header_ser *header_ser; + + if (sh->count =3D=3D LUO_SESSION_MAX) + return -ENOMEM; + + if (sh->header_ser) + return 0; + + header_ser =3D kho_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT); + if (IS_ERR(header_ser)) + return PTR_ERR(header_ser); + + sh->header_ser =3D header_ser; + sh->ser =3D (void *)(header_ser + 1); + return 0; +} + static int luo_session_insert(struct luo_session_header *sh, struct luo_session *session) { struct luo_session *it; + int err; =20 guard(rwsem_write)(&sh->rwsem); =20 @@ -183,8 +205,9 @@ static int luo_session_insert(struct luo_session_header= *sh, * for new session. */ if (sh =3D=3D &luo_session_global.outgoing) { - if (sh->count =3D=3D LUO_SESSION_MAX) - return -ENOMEM; + err =3D luo_session_grow_ser(sh); + if (err) + return err; } =20 /* @@ -524,21 +547,10 @@ int luo_session_retrieve(const char *name, struct fil= e **filep) return err; } =20 -int __init luo_session_setup_outgoing(u64 *sessions_pa) +void __init luo_session_setup_outgoing(u64 *sessions_pa) { - struct luo_session_header_ser *header_ser; - - header_ser =3D kho_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT); - if (IS_ERR(header_ser)) - return PTR_ERR(header_ser); - - *sessions_pa =3D virt_to_phys(header_ser); - - luo_session_global.outgoing.header_ser =3D header_ser; - luo_session_global.outgoing.ser =3D (void *)(header_ser + 1); + luo_session_global.outgoing.sessions_pa =3D sessions_pa; luo_session_global.outgoing.active =3D true; - - return 0; } =20 int __init luo_session_setup_incoming(u64 sessions_pa) @@ -644,6 +656,8 @@ int luo_session_serialize(void) =20 down_write(&luo_session_serialize_rwsem); down_write(&sh->rwsem); + *sh->sessions_pa =3D 0; + list_for_each_entry(session, &sh->list, list) { err =3D luo_session_freeze_one(session, &sh->ser[i]); if (err) @@ -653,7 +667,11 @@ int luo_session_serialize(void) sizeof(sh->ser[i].name)); i++; } - sh->header_ser->count =3D sh->count; + + if (sh->header_ser && sh->count > 0) { + sh->header_ser->count =3D sh->count; + *sh->sessions_pa =3D virt_to_phys(sh->header_ser); + } up_write(&sh->rwsem); =20 return 0; --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qt1-f177.google.com (mail-qt1-f177.google.com [209.85.160.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18FC53D75A2 for ; Wed, 3 Jun 2026 15:45:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501556; cv=none; b=mfDv20op+sdsMIO+F1O18efZSX50hZJjLlIjauX56Oe0IGt5o6DZ+gPQrnzG8ZsdfMorxuvqVGY3LYUgnMXLJWmfTJcujyLYo4fWwDQQt0h4t2udwt1tgXk2Sdc5OjXIQR+pqAPwfuWMfUwmo0RpY502mOsBS1E+UF18pEGTIpk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501556; c=relaxed/simple; bh=YVQUMZe5511L4bm5GN55nDryAkXDkubSfASy5mdkqL8=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NUzNSDkxqb7FBDhFisK357I+OHw3ortQHVil59YqneUaBaQbOVoLVAec7qGH3LHFDfb2XEGzzNjR1ts2AvfXEw6A9TROYx3Iw/8IFh5/Q4cV2JMisg0Ci3RoVqT++Bn+ASY8R9RYHh1duJp1NRxPljllQvn82Y4pjbXJKThPdo8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=DGS7aa0N; arc=none smtp.client-ip=209.85.160.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="DGS7aa0N" Received: by mail-qt1-f177.google.com with SMTP id d75a77b69052e-516d634956fso146734011cf.2 for ; Wed, 03 Jun 2026 08:45:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501551; x=1781106351; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=G54EjScdsoAHhtz7nw9E64EqCSfODXiX67qASj3ZuAY=; b=DGS7aa0N72D1io++OhjFSz2zsvIlEivDFVzGNVjxAROqJkzoEhpxqpau3jqw8lFSPB LcLK7HRT/JurC3wL7nKXVsZj8ZxaIrW7wUobDjPMObkvROzzlc/9bEsa1Ye0GtetXXSu V+U6wtehv39+fF3mdAhEK678iJzka2K1IH+tfGI92rkD73hNjTaRk78s60ARMC1ZGUNd oStJtwKp7xf9KL4GSyB8oOxd2PQBXoO4nkGqjpLkJ3zDO63uvDPasunQR852axRjHS8u bG+M+24h9+9ONZ6USSB7kjlA7A2/hR4kSjy327gB0KuEQlKU5DnRq3Jm0lHz5s6/W0nb X6bA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501551; x=1781106351; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=G54EjScdsoAHhtz7nw9E64EqCSfODXiX67qASj3ZuAY=; b=Zsj7loz1ohmEFRtRhJThauXVHCHql+exSvWYVuiBWDd3/ycK9bpZTfpviFrsV+Woi5 YF4V8UTQb6RGrfflPpweasZrV5oyac9UqNoqRYyhv5mRvh47supZWt8DgbTCXXndDtIg MsIKXtu5+PuZF+lzRikoWc3yvhJRQJnmw4z09m2tFYHokVjPJchpzTCn2z8hYmE9bk3c yU60FnH9aJzfzkkTGt5c/0GlkbMHpE67DH4RWsi4o4lgUhVSHAyMqzfZeu5ZxmaThLiL vCNh5IdGjIELp/sGYULSyXkeV8Xnt2tcB5fUsZLN7SZSyylhX+KuBgBlxxyQFPFfcfwx b99A== X-Forwarded-Encrypted: i=1; AFNElJ/QJJCFthLYG0KQKsJEm+Weh7JJ8h3TzwqIgfCVqGItpq+Y9eQnHFXVSLhv7tw/ocG05DCHsYkd7/2yAvA=@vger.kernel.org X-Gm-Message-State: AOJu0Yz37UCRY0wsqfkwXZ6PEeqUS7WRl5G8ljgAEE7k0zDkIs/fcd/2 +SnwmddZ+GEhTed8lrhhbSuahz2ousxzlY71XVGyJdu37YhWxvndOHVzmuQMGKut0iw= X-Gm-Gg: Acq92OGK22A/c7dYkMr66rcxEBjRpYFaiA3ACRr0FInst4Dlx/b7TUMjlkgznoocO4E xxUVqOtCJtHOdzMFhyIOSB2s+iR4XHAGSCTuE2kVmtbDBFwISc8EwS7Zw4g/ftb7Q0v2YE/KrvT Mu71D9b9OieNaMyaeXaApe7gRvIv2HTH383iUNd2ephAWHQKj406Vqd6z56rbFBnGzYiQxj1L5C HgQ9SZ+QDn3Fyr8WvBU+xx/a+rxzfqTf+R/6icN+4Pv40BQGJgcDgronI1dD6/pLH+Dn42oiAgZ WHU+KlkG1sQpMkNATE4bp8LV4kio2lvjlWmtIW+86b197ROVNlJTmW9nxkXDSeGBR4U0/7Nx5w7 34FACpP/Qa/CLVhDq4bvo+e2GY1ADBMrzMvM+AB7wPJo9y8+GTMyKc7JC9bLdTNHWOsBGgmE1c2 eN2htfQYp2rhV0VEy5VhaTbfn+ye71jYYxritxHdUs678xZ9NV49lha+X9qBXHSQ== X-Received: by 2002:a05:622a:8416:20b0:50b:38c1:c6a with SMTP id d75a77b69052e-5177860194fmr45451841cf.19.1780501550650; Wed, 03 Jun 2026 08:45:50 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-51775c4d7absm26135361cf.11.2026.06.03.08.45.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:45:50 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 09/13] liveupdate: Remove limit on the number of sessions Date: Wed, 3 Jun 2026 15:43:58 +0000 Message-ID: <20260603154402.468928-10-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, the number of LUO sessions is limited by a fixed number of pre-allocated pages for serialization (16 pages, allowing for ~819 sessions). This limitation is problematic if LUO is used to support things such as systemd file descriptor store, and would be used not just as VM memory but to save other states on the machine. Remove this limit by transitioning to a linked-block approach for session metadata serialization. Instead of a single contiguous block, session metadata is now stored in a chain of 16-page blocks. Each block starts with a header containing the physical address of the next block and the number of session entries in the current block. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- include/linux/kho/abi/luo.h | 23 +------ kernel/liveupdate/luo_session.c | 113 +++++++++++++++----------------- 2 files changed, 55 insertions(+), 81 deletions(-) diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h index 9a4fe491812b..03d940d0f9bb 100644 --- a/include/linux/kho/abi/luo.h +++ b/include/linux/kho/abi/luo.h @@ -33,11 +33,6 @@ * It includes the compatibility string, the liveupdate-number, and po= inters * to sessions and FLBs. * - * - struct luo_session_header_ser: - * Header for the session array. Contains the total page count of the - * preserved memory block and the number of `struct luo_session_ser` - * entries that follow. - * * - struct luo_session_ser: * Metadata for a single session, including its name and a physical po= inter * to another preserved memory block containing an array of @@ -63,13 +58,14 @@ #define _LINUX_KHO_ABI_LUO_H =20 #include +#include #include =20 /* * The LUO state is registered under this KHO entry name. */ #define LUO_KHO_ENTRY_NAME "LUO" -#define LUO_ABI_COMPATIBLE "luo-v3" +#define LUO_ABI_COMPATIBLE "luo-v4" #define LUO_ABI_COMPAT_LEN ALIGN(sizeof(LUO_ABI_COMPATIBLE), 8) =20 /** @@ -118,21 +114,6 @@ struct luo_file_set_ser { u64 count; } __packed; =20 -/** - * struct luo_session_header_ser - Header for the serialized session data = block. - * @count: The number of `struct luo_session_ser` entries that immediately - * follow this header in the memory block. - * - * This structure is located at the beginning of a contiguous block of - * physical memory preserved across the kexec. It provides the necessary - * metadata to interpret the array of session entries that follow. - * - * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated. - */ -struct luo_session_header_ser { - u64 count; -} __packed; - /** * struct luo_session_ser - Represents the serialized metadata for a LUO s= ession. * @name: The unique name of the session, provided by the userspac= e at diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index 2411849a34e3..b79b2a488974 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -24,9 +24,10 @@ * ioctls on /dev/liveupdate. * * - Serialization: Session metadata is preserved using the KHO framework.= When - * a live update is triggered via kexec, an array of `struct luo_session= _ser` - * is populated and placed in a preserved memory region. The physical ad= dress - * of this array is stored in the centralized `struct luo_ser` structure. + * a live update is triggered via kexec, session metadata is serialized = into + * a chain of linked-blocks and placed in a preserved memory region. The + * physical address of the first block header is stored in the centraliz= ed + * `struct luo_ser` structure. * * Session Lifecycle: * @@ -89,6 +90,7 @@ #include #include #include +#include #include #include #include @@ -98,23 +100,14 @@ #include #include "luo_internal.h" =20 -/* 16 4K pages, give space for 744 sessions */ -#define LUO_SESSION_PGCNT 16ul -#define LUO_SESSION_MAX (((LUO_SESSION_PGCNT << PAGE_SHIFT) - \ - sizeof(struct luo_session_header_ser)) / \ - sizeof(struct luo_session_ser)) - static DECLARE_RWSEM(luo_session_serialize_rwsem); - /** * struct luo_session_header - Header struct for managing LUO sessions. * @count: The number of sessions currently tracked in the @list. * @list: The head of the linked list of `struct luo_session` insta= nces. * @rwsem: A read-write semaphore providing synchronized access to t= he * session list and other fields in this structure. - * @header_ser: The header data of serialization array. - * @ser: The serialized session data (an array of - * `struct luo_session_ser`). + * @block_set: The set of serialization blocks. * @sessions_pa: Points to the location of sessions_pa within struct luo_s= er. * @active: Set to true when first initialized. If previous kernel di= d not * send session data, active stays false for incoming. @@ -123,8 +116,7 @@ struct luo_session_header { long count; struct list_head list; struct rw_semaphore rwsem; - struct luo_session_header_ser *header_ser; - struct luo_session_ser *ser; + struct kho_block_set block_set; u64 *sessions_pa; bool active; }; @@ -143,10 +135,14 @@ static struct luo_session_global luo_session_global = =3D { .incoming =3D { .list =3D LIST_HEAD_INIT(luo_session_global.incoming.list), .rwsem =3D __RWSEM_INITIALIZER(luo_session_global.incoming.rwsem), + .block_set =3D KHO_BLOCK_SET_INIT(luo_session_global.incoming.block_set, + sizeof(struct luo_session_ser)), }, .outgoing =3D { .list =3D LIST_HEAD_INIT(luo_session_global.outgoing.list), .rwsem =3D __RWSEM_INITIALIZER(luo_session_global.outgoing.rwsem), + .block_set =3D KHO_BLOCK_SET_INIT(luo_session_global.outgoing.block_set, + sizeof(struct luo_session_ser)), }, }; =20 @@ -173,25 +169,6 @@ static void luo_session_free(struct luo_session *sessi= on) kfree(session); } =20 -static int luo_session_grow_ser(struct luo_session_header *sh) -{ - struct luo_session_header_ser *header_ser; - - if (sh->count =3D=3D LUO_SESSION_MAX) - return -ENOMEM; - - if (sh->header_ser) - return 0; - - header_ser =3D kho_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT); - if (IS_ERR(header_ser)) - return PTR_ERR(header_ser); - - sh->header_ser =3D header_ser; - sh->ser =3D (void *)(header_ser + 1); - return 0; -} - static int luo_session_insert(struct luo_session_header *sh, struct luo_session *session) { @@ -205,7 +182,7 @@ static int luo_session_insert(struct luo_session_header= *sh, * for new session. */ if (sh =3D=3D &luo_session_global.outgoing) { - err =3D luo_session_grow_ser(sh); + err =3D kho_block_set_grow(&sh->block_set, sh->count + 1); if (err) return err; } @@ -232,6 +209,8 @@ static void luo_session_remove(struct luo_session_heade= r *sh, guard(rwsem_write)(&sh->rwsem); list_del(&session->list); sh->count--; + if (sh =3D=3D &luo_session_global.outgoing) + kho_block_set_shrink(&sh->block_set, sh->count); } =20 static int luo_session_finish_one(struct luo_session *session) @@ -555,15 +534,17 @@ void __init luo_session_setup_outgoing(u64 *sessions_= pa) =20 int __init luo_session_setup_incoming(u64 sessions_pa) { - struct luo_session_header_ser *header_ser; + struct luo_session_header *sh =3D &luo_session_global.incoming; + int err; =20 - if (sessions_pa) { - header_ser =3D phys_to_virt(sessions_pa); - luo_session_global.incoming.header_ser =3D header_ser; - luo_session_global.incoming.ser =3D (void *)(header_ser + 1); - luo_session_global.incoming.active =3D true; - } + if (!sessions_pa) + return 0; =20 + err =3D kho_block_set_restore(&sh->block_set, sessions_pa); + if (err) + return err; + + sh->active =3D true; return 0; } =20 @@ -605,6 +586,8 @@ int luo_session_deserialize(void) { struct luo_session_header *sh =3D &luo_session_global.incoming; static bool is_deserialized; + struct luo_session_ser *ser; + struct kho_block_set_it it; static int saved_err; int err; =20 @@ -631,18 +614,19 @@ int luo_session_deserialize(void) * userspace to detect the failure and trigger a reboot, which will * reliably reset devices and reclaim memory. */ - for (int i =3D 0; i < sh->header_ser->count; i++) { - err =3D luo_session_deserialize_one(sh, &sh->ser[i]); + kho_block_set_it_init(&it, &sh->block_set); + while ((ser =3D kho_block_set_it_read_entry(&it))) { + err =3D luo_session_deserialize_one(sh, ser); if (err) goto save_err; } =20 - kho_restore_free(sh->header_ser); - sh->header_ser =3D NULL; - sh->ser =3D NULL; + kho_block_set_destroy(&sh->block_set); =20 return 0; + save_err: + kho_block_set_destroy(&sh->block_set); saved_err =3D err; return err; } @@ -651,36 +635,45 @@ int luo_session_serialize(void) { struct luo_session_header *sh =3D &luo_session_global.outgoing; struct luo_session *session; - int i =3D 0; + struct kho_block_set_it it; int err; =20 down_write(&luo_session_serialize_rwsem); down_write(&sh->rwsem); *sh->sessions_pa =3D 0; =20 + kho_block_set_it_init(&it, &sh->block_set); + list_for_each_entry(session, &sh->list, list) { - err =3D luo_session_freeze_one(session, &sh->ser[i]); - if (err) + struct luo_session_ser *ser =3D kho_block_set_it_reserve_entry(&it); + + /* This should not fail normally as blocks were pre-allocated */ + if (WARN_ON_ONCE(!ser)) { + err =3D -ENOSPC; goto err_undo; + } =20 - strscpy(sh->ser[i].name, session->name, - sizeof(sh->ser[i].name)); - i++; - } + err =3D luo_session_freeze_one(session, ser); + if (err) { + kho_block_set_it_prev(&it); + goto err_undo; + } =20 - if (sh->header_ser && sh->count > 0) { - sh->header_ser->count =3D sh->count; - *sh->sessions_pa =3D virt_to_phys(sh->header_ser); + strscpy(ser->name, session->name, sizeof(ser->name)); } + + if (sh->count > 0) + *sh->sessions_pa =3D kho_block_set_head_pa(&sh->block_set); up_write(&sh->rwsem); =20 return 0; =20 err_undo: list_for_each_entry_continue_reverse(session, &sh->list, list) { - i--; - luo_session_unfreeze_one(session, &sh->ser[i]); - memset(sh->ser[i].name, 0, sizeof(sh->ser[i].name)); + struct luo_session_ser *ser =3D kho_block_set_it_prev(&it); + + luo_session_unfreeze_one(session, ser); + memset(ser->name, 0, sizeof(ser->name)); } up_write(&sh->rwsem); up_write(&luo_session_serialize_rwsem); --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qv1-f41.google.com (mail-qv1-f41.google.com [209.85.219.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CBB6C3DA5CB for ; Wed, 3 Jun 2026 15:46:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501570; cv=none; b=Pbltve8w45USM2OVgbPFQ/EmKAIHBCDKsZzp4Jsf7YeT0zrqNyDlIMmV5MkuApi3S9Haitolw8wXAn+akOUy9mQHhDUqlGnK/LCS35M4bZH3Z8wQvzJs8xhineGM7caZyWXGKQkuERhluMtM87Izgb6hbOi4sfRfXQRCguGP4Sg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501570; c=relaxed/simple; bh=ZRfdPsLnxtNJ9B9lC8QrfK+48ouchkFgHKpkmfHzPJY=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ReQ85J7luCJTgPMRD+Uxjs5W1ileu9bXbPXGWeWsEh/66bli0pRdxHME6/4TU3u+DT78w6jzRPIFbkgqMhBDo70500b+KlZUrkRU7FYuKwSndtlkHHHXpF+S12Ga43QTPUsDGOdFe25eI91KaOqO8tqHugdb+ItfkmQ6Z4W3YL0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=MmrWcE/x; arc=none smtp.client-ip=209.85.219.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="MmrWcE/x" Received: by mail-qv1-f41.google.com with SMTP id 6a1803df08f44-8ccf887de87so51731816d6.0 for ; Wed, 03 Jun 2026 08:46:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501563; x=1781106363; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=I7RY0aQRmzwpMQlV2C0KvIb/sAJhNYK+jOGgyIc3BtM=; b=MmrWcE/xnl4X2Em94iROuhSxb4cNV8c3uEgoLDq08IdF8Wg50ehX1nfDstDNoy02z/ mvKU0jaLgymH/8OB/GapzaLsd/Fo+oiMYeZN/liNqdcqdh6RVyB2J71ZReQWO6+mpDXl zsFpVqSCo8cllJA1wyl4H/impUQB5VlS7gR/Ppewj2vGe8BGPh+0Iq91Uuwzm2p1sUJT 2tnqc6ehJmx4jZnFgVqfgm48OulUpSr4DXDAywDODZvIxViNV4FO2o1qCMwcSUJvldge WBTFqVx/6s+nBGqUsIfdPOieNF8diBgo2Amrc7r5IKtbLAmL1FTMOKt50rNKJU/givE+ 5sMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501563; x=1781106363; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=I7RY0aQRmzwpMQlV2C0KvIb/sAJhNYK+jOGgyIc3BtM=; b=V9PXqWgW8ZG4AaBANPW2Jp+CjbFXWtal4af25wN87zya+s8wrNbZuUjcm+V5ce1QFN 1bgWatmtkyx/EWoVDkpguT69nfR3OX0ZE/3vPiKNjrSGqAVMRT0C/sfmZvtzpriAxxcP FnTYCLi7UcxknWuVgWZN92BwQ2/FOQqfk4pXHpg8wPJVbVbCkwGtnxxrVfo3OBxTRW5I OKB6uG/8jo+LbCTFdgOU3E4xb46O+3jXXXVw+JM6ixuoXnZ5mNFikItKt1A+47tMrpOY mDUKyhY1f1CL06Q4WXtk4OvXKrVUsMf22FM+7qcNN0R3pJCatZiXXB443IOgBeo3M5Jt HueA== X-Forwarded-Encrypted: i=1; AFNElJ/ZbdWx5/izXazAuB1eK0zjUN3Atrg6Qb5/7GSdrCNSCehwegp2kcvlERfrHM1Fp/XXOCNr7igXlpnKZzk=@vger.kernel.org X-Gm-Message-State: AOJu0YxWYDmHE5oHwKzQqcrEXuNzgyvXClY/+Dakj1lSkeWYuoM+ddGX 2/YiYRPapUIodS4AzI+i09Vay0edgCKotdg4TEVTV08D3DNREhf2d/t+1JfO/HF9/Mw= X-Gm-Gg: Acq92OGbN4hIOGFWXKjGjxgL/YM14FUtdzbjivsmiwwSWTV4rddIBwMXt696AAPcMsi jZEu5rc5QeCxiY44U+I67f6qLUBdIyIXDdGR6r2ywWCvFbshgVWuvIED9/zSiw9TTLKLGpjW5p7 CMPUvmKw7Sz06r4ME37xpbIMtKPWBZE7/m0gdzs3gOfoge8hWL6RbSUlDWsQKpbPxpL8LJcU7XE YE1bY/p6eqZGtwCFOFTtqdC/Hnl0Ppk0l0N0FO4ZgM3DG9jZOzNcsSHjL+xT4zHqJOdCqCaIEo4 /rGyNI9Qn+GSAF13w5aK6KzoGc55BBf1Ymt8yNocJKRFKYj7Cw1bIkfIzy+R2Ur+8P4BhYtHBle CiMiBeQ5dnJjzPnrhfW3Ah0dIfdg808YNF3Vlc7n/uT0ArzoljAFvAHGy+5srA7jN1jxVk5VmVX hF5sHAdzVCBUGDzd7eQi5oO8smbJNEgqhm4i+qPNYkN//gCFqvumiPBiVlBOcD8Q== X-Received: by 2002:a05:6214:c68:b0:8ce:ba04:7bfe with SMTP id 6a1803df08f44-8cece1668a1mr51109436d6.46.1780501562561; Wed, 03 Jun 2026 08:46:02 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8ceccd9dfc1sm23450476d6.4.2026.06.03.08.46.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:46:02 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 10/13] liveupdate: Remove limit on the number of files per session Date: Wed, 3 Jun 2026 15:43:59 +0000 Message-ID: <20260603154402.468928-11-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To remove the fixed limit on the number of preserved files per session, transition the file metadata serialization from a single contiguous memory block to a chain of linked blocks. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- include/linux/kho/abi/luo.h | 13 +-- kernel/liveupdate/luo_file.c | 138 ++++++++++++++----------------- kernel/liveupdate/luo_internal.h | 6 +- 3 files changed, 74 insertions(+), 83 deletions(-) diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h index 03d940d0f9bb..288076de6d4a 100644 --- a/include/linux/kho/abi/luo.h +++ b/include/linux/kho/abi/luo.h @@ -35,8 +35,8 @@ * * - struct luo_session_ser: * Metadata for a single session, including its name and a physical po= inter - * to another preserved memory block containing an array of - * `struct luo_file_ser` for all files in that session. + * to the first `struct kho_block_header_ser` for all files in that se= ssion. + * Multiple blocks are linked via the `next` field in the header. * * - struct luo_file_ser: * Metadata for a single preserved file. Contains the `compatible` str= ing to @@ -65,7 +65,7 @@ * The LUO state is registered under this KHO entry name. */ #define LUO_KHO_ENTRY_NAME "LUO" -#define LUO_ABI_COMPATIBLE "luo-v4" +#define LUO_ABI_COMPATIBLE "luo-v5" #define LUO_ABI_COMPAT_LEN ALIGN(sizeof(LUO_ABI_COMPATIBLE), 8) =20 /** @@ -102,9 +102,10 @@ struct luo_file_ser { =20 /** * struct luo_file_set_ser - Represents the serialized metadata for file s= et - * @files: The physical address of a contiguous memory block that holds - * the serialized state of files (array of luo_file_ser) in this= file - * set. + * @files: The physical address of the first `struct kho_block_header_se= r`. + * This structure is the header for a block of memory containing + * an array of `struct luo_file_ser` entries. Multiple blocks are + * linked via the `next` field in the header. * @count: The total number of files that were part of this session duri= ng * serialization. Used for iteration and validation during * restoration. diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c index 9eec07a9e9fc..c39f96961a85 100644 --- a/kernel/liveupdate/luo_file.c +++ b/kernel/liveupdate/luo_file.c @@ -118,11 +118,6 @@ static LIST_HEAD(luo_file_handler_list); /* Keep track of files being preserved by LUO */ static DEFINE_XARRAY(luo_preserved_files); =20 -/* 2 4K pages, give space for 128 files per file_set */ -#define LUO_FILE_PGCNT 2ul -#define LUO_FILE_MAX \ - ((LUO_FILE_PGCNT << PAGE_SHIFT) / sizeof(struct luo_file_ser)) - /** * struct luo_file - Represents a single preserved file instance. * @fh: Pointer to the &struct liveupdate_file_handler that man= ages @@ -174,39 +169,6 @@ struct luo_file { u64 token; }; =20 -static int luo_alloc_files_mem(struct luo_file_set *file_set) -{ - size_t size; - void *mem; - - if (file_set->files) - return 0; - - WARN_ON_ONCE(file_set->count); - - size =3D LUO_FILE_PGCNT << PAGE_SHIFT; - mem =3D kho_alloc_preserve(size); - if (IS_ERR(mem)) - return PTR_ERR(mem); - - file_set->files =3D mem; - - return 0; -} - -static void luo_free_files_mem(struct luo_file_set *file_set) -{ - /* If file_set has files, no need to free preservation memory */ - if (file_set->count) - return; - - if (!file_set->files) - return; - - kho_unpreserve_free(file_set->files); - file_set->files =3D NULL; -} - static unsigned long luo_get_id(struct liveupdate_file_handler *fh, struct file *file) { @@ -276,16 +238,15 @@ int luo_preserve_file(struct luo_file_set *file_set, = u64 token, int fd) if (luo_token_is_used(file_set, token)) return -EEXIST; =20 - if (file_set->count =3D=3D LUO_FILE_MAX) - return -ENOSPC; + err =3D kho_block_set_grow(&file_set->block_set, file_set->count + 1); + if (err) + return err; =20 file =3D fget(fd); - if (!file) - return -EBADF; - - err =3D luo_alloc_files_mem(file_set); - if (err) - goto err_fput; + if (!file) { + err =3D -EBADF; + goto err_shrink; + } =20 err =3D -ENOENT; down_read(&luo_register_rwlock); @@ -300,7 +261,7 @@ int luo_preserve_file(struct luo_file_set *file_set, u6= 4 token, int fd) =20 /* err is still -ENOENT if no handler was found */ if (err) - goto err_free_files_mem; + goto err_fput; =20 err =3D xa_insert(&luo_preserved_files, luo_get_id(fh, file), file, GFP_KERNEL); @@ -343,10 +304,10 @@ int luo_preserve_file(struct luo_file_set *file_set, = u64 token, int fd) xa_erase(&luo_preserved_files, luo_get_id(fh, file)); err_module_put: module_put(fh->ops->owner); -err_free_files_mem: - luo_free_files_mem(file_set); err_fput: fput(file); +err_shrink: + kho_block_set_shrink(&file_set->block_set, file_set->count); =20 return err; } @@ -392,13 +353,14 @@ void luo_file_unpreserve_files(struct luo_file_set *f= ile_set) =20 list_del(&luo_file->list); file_set->count--; + kho_block_set_shrink(&file_set->block_set, file_set->count); =20 fput(luo_file->file); mutex_destroy(&luo_file->mutex); kfree(luo_file); } =20 - luo_free_files_mem(file_set); + kho_block_set_destroy(&file_set->block_set); } =20 static int luo_file_freeze_one(struct luo_file_set *file_set, @@ -454,7 +416,7 @@ static void __luo_file_unfreeze(struct luo_file_set *fi= le_set, luo_file_unfreeze_one(file_set, luo_file); } =20 - memset(file_set->files, 0, LUO_FILE_PGCNT << PAGE_SHIFT); + kho_block_set_clear(&file_set->block_set); } =20 /** @@ -493,19 +455,24 @@ static void __luo_file_unfreeze(struct luo_file_set *= file_set, int luo_file_freeze(struct luo_file_set *file_set, struct luo_file_set_ser *file_set_ser) { - struct luo_file_ser *file_ser =3D file_set->files; struct luo_file *luo_file; + struct kho_block_set_it it; int err; - int i; =20 if (!file_set->count) return 0; =20 - if (WARN_ON(!file_ser)) - return -EINVAL; + kho_block_set_it_init(&it, &file_set->block_set); =20 - i =3D 0; list_for_each_entry(luo_file, &file_set->files_list, list) { + struct luo_file_ser *file_ser =3D kho_block_set_it_reserve_entry(&it); + + /* This should not fail normally as blocks were pre-allocated */ + if (WARN_ON_ONCE(!file_ser)) { + err =3D -ENOSPC; + goto err_unfreeze; + } + err =3D luo_file_freeze_one(file_set, luo_file); if (err < 0) { pr_warn("Freeze failed for token[%#0llx] handler[%s] err[%pe]\n", @@ -514,16 +481,14 @@ int luo_file_freeze(struct luo_file_set *file_set, goto err_unfreeze; } =20 - strscpy(file_ser[i].compatible, luo_file->fh->compatible, - sizeof(file_ser[i].compatible)); - file_ser[i].data =3D luo_file->serialized_data; - file_ser[i].token =3D luo_file->token; - i++; + strscpy(file_ser->compatible, luo_file->fh->compatible, + sizeof(file_ser->compatible)); + file_ser->data =3D luo_file->serialized_data; + file_ser->token =3D luo_file->token; } =20 file_set_ser->count =3D file_set->count; - if (file_set->files) - file_set_ser->files =3D virt_to_phys(file_set->files); + file_set_ser->files =3D kho_block_set_head_pa(&file_set->block_set); =20 return 0; =20 @@ -741,14 +706,12 @@ int luo_file_finish(struct luo_file_set *file_set) module_put(luo_file->fh->ops->owner); list_del(&luo_file->list); file_set->count--; + kho_block_set_shrink(&file_set->block_set, file_set->count); mutex_destroy(&luo_file->mutex); kfree(luo_file); } =20 - if (file_set->files) { - kho_restore_free(file_set->files); - file_set->files =3D NULL; - } + kho_block_set_destroy(&file_set->block_set); =20 return 0; } @@ -822,16 +785,18 @@ int luo_file_deserialize(struct luo_file_set *file_se= t, struct luo_file_set_ser *file_set_ser) { struct luo_file_ser *file_ser; + struct kho_block_set_it it; int err; - u64 i; =20 if (!file_set_ser->files) { WARN_ON(file_set_ser->count); return 0; } =20 - file_set->count =3D file_set_ser->count; - file_set->files =3D phys_to_virt(file_set_ser->files); + file_set->count =3D 0; + err =3D kho_block_set_restore(&file_set->block_set, file_set_ser->files); + if (err) + return err; =20 /* * Note on error handling: @@ -848,25 +813,50 @@ int luo_file_deserialize(struct luo_file_set *file_se= t, * userspace to detect the failure and trigger a reboot, which will * reliably reset devices and reclaim memory. */ - file_ser =3D file_set->files; - for (i =3D 0; i < file_set->count; i++) { - err =3D luo_file_deserialize_one(file_set, &file_ser[i]); + kho_block_set_it_init(&it, &file_set->block_set); + while ((file_ser =3D kho_block_set_it_read_entry(&it))) { + err =3D luo_file_deserialize_one(file_set, file_ser); if (err) - return err; + goto err_destroy_blocks; + file_set->count++; + } + + if (file_set->count !=3D file_set_ser->count) { + pr_warn("File count mismatch: expected %llu, found %llu\n", + file_set_ser->count, file_set->count); + err =3D -EINVAL; + goto err_destroy_blocks; } =20 return 0; + +err_destroy_blocks: + while (!list_empty(&file_set->files_list)) { + struct luo_file *luo_file; + + luo_file =3D list_first_entry(&file_set->files_list, + struct luo_file, list); + list_del(&luo_file->list); + module_put(luo_file->fh->ops->owner); + mutex_destroy(&luo_file->mutex); + kfree(luo_file); + } + file_set->count =3D 0; + kho_block_set_destroy(&file_set->block_set); + return err; } =20 void luo_file_set_init(struct luo_file_set *file_set) { INIT_LIST_HEAD(&file_set->files_list); + kho_block_set_init(&file_set->block_set, sizeof(struct luo_file_ser)); } =20 void luo_file_set_destroy(struct luo_file_set *file_set) { WARN_ON(file_set->count); WARN_ON(!list_empty(&file_set->files_list)); + WARN_ON(!kho_block_set_is_empty(&file_set->block_set)); } =20 /** diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_inter= nal.h index ee18f9a11b91..64879ffe7378 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -10,6 +10,7 @@ =20 #include #include +#include =20 struct luo_ucmd { void __user *ubuffer; @@ -44,14 +45,13 @@ static inline int luo_ucmd_respond(struct luo_ucmd *ucm= d, * struct luo_file_set - A set of files that belong to the same sessions. * @files_list: An ordered list of files associated with this session, it = is * ordered by preservation time. - * @files: The physically contiguous memory block that holds the seri= alized - * state of files. + * @block_set: The set of serialization blocks. * @count: A counter tracking the number of files currently stored in= the * @files_list for this session. */ struct luo_file_set { struct list_head files_list; - struct luo_file_ser *files; + struct kho_block_set block_set; u64 count; }; =20 --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qk1-f178.google.com (mail-qk1-f178.google.com [209.85.222.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93AFF3D648F for ; Wed, 3 Jun 2026 15:46:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501579; cv=none; b=FfRTFb5rGdBxClrhFVlOGnUiym7ek3ot3/0JhQwjrv045r0Hdz/mL1GklfqHN+dtLcsEdn1p+ldjMS4nC5GG+ANzNZvoPCdnqRNuViw7LkwHYCEHl2g3o8JeXmAqdjTv5DdX0Fby9RRivDG4JtWx0fk7sfQlhZxLVwylov8ufmM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501579; c=relaxed/simple; bh=GqAk9WL9MH7rJUNKZjopN3vwXWkbaerKBCceA/gzAA0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nQbpnWn7f27N48TC4//YcKAZrGS6qPQfMAsTuQrorw7j2VsEU/9Gou1myjMGTGpcwwmGO4WO5muLqRCLSDLGzsyY4bnlplXTCUB8mWHyfEDACOyt9gYJrZqasrB+a30a39n5d7Q8P6GWbIteeuxhaFyhIHVyc7LDliZcfC52kJ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=ipnRHvDc; arc=none smtp.client-ip=209.85.222.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="ipnRHvDc" Received: by mail-qk1-f178.google.com with SMTP id af79cd13be357-9158643e538so137627485a.1 for ; Wed, 03 Jun 2026 08:46:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501574; x=1781106374; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=SdAegEf5u3em8MUzB4xyEunyt/xoJrJRQD9FIOINoRs=; b=ipnRHvDcRgc22J6ABdtyIpEkQlNGqm9/4TwfS19Tig2X1hzA5RDKFqB8ojq/RrUGI1 ya5fd+ovnwg2/D6Rvrt75qygXjVeJ/VKahKFYIDp93/F7Ypc0aLICRZipqsvzc3YlCQK UWrVeWU5TI/XQhAlsOMAbo+aZOkmWl3DBZVJNZDcLdbhm3xvmQG5cAVhkA/qZ4AnyNeP NETyoeclkxqufO+6FEFgD0iOk9Bbjl/Q0QK6SMvIPgSuqQlyo0tgEC/Q2PKoIDYCHotQ whasTzteNt1mj4xR6qjWuuW/tfr0GC1t7hpTEScidQS5a3xzhJdcNqWulq9lEvTxM8iR nL9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501574; x=1781106374; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=SdAegEf5u3em8MUzB4xyEunyt/xoJrJRQD9FIOINoRs=; b=b+ArH/d5SBtCiu0LPtp9Vqm0gxhMaJ6LfIj3cWo0juUsRi8pt9KGcncR9VpXU3KnNG qRDIbLlELnG6tyIA7UvrG7R79pJoXhYcXFQ0tmdHWqbT9XuyX7OClHd2+yDVwKKJ7fCg Ilb/Tab5X6VZpoDW31FHMGLnzYYWaJztwbvPgdtrqbRRMg3IW88SNTCtuqFJ5sZuaOnm Hm7Uk4wvxHp3J5kkqxav4pLRxBdA98AUHr9TYvo5DzsCSmj+ap6pNLIEv9ORRlCE7fag L/w1rgubf9Mb6WSEgoPgubAxdDS/m/11htFBoHg6M3Nb1cL4ErGxD2akcJDQIM2DIzka vEKw== X-Forwarded-Encrypted: i=1; AFNElJ+AiNT8NUQDeq6z1/Awj1x9gkR4J1K+AlXqKeMNr97uqBhfjdB5px4xdCeMXbHXeA1YWdNmSOU8PtJot6c=@vger.kernel.org X-Gm-Message-State: AOJu0YzayOVwV1iHXO+NIc9Er5wpnb3OWwalGrDSN0p8PwiYqHBrh1rA 36ykWnnNVqvE0MJzwHjT6BC2GQFQUCUKB8eAZGclq/l99D9TRBadrCub820MEF67fz8= X-Gm-Gg: Acq92OEpn8dc/d0ARpF3XsJcQOyI5VbuDGVrlnZPVN7BlZ6Fx/z9HH0rPaYpgF2rNy9 RY14I6DnUBzOHAQSJi8RcauIDFxNnjFVV7FZczbq1hLLd3obQdUvSxE3mX49pUldiXlZ0/nuJIG v8vz89CC4UpZxdNY3o9fqO3VxwfOQBHhMxqSVCYheX7urTl2XO9dx6gnLpKpH6EQdqMORInGtWh VdNUt6ijMDFuEKsIa4WBzNA1DK3dkGTMo6B1uLFP77M2mD59wzr3ac0EhCUKFhSbSOMIYqpPmLe AF57Okr+dz8xnqocb+Js1jIhm2NuYc/xMhd6Xjxg4T5eN1r8ncktAI509EApVxtrOGcYHw0xlMS Bu4Ke9jwjXKoWf0pj8SIRtdfRTlJQlIi+0C22fA+y6Jhn+DihArhYkGQwMmBDSNZTYWf6+WimrV FbGwJ1HpIzUjXKVfnW9WpCsh3FShZRiszeyyxW0H9ahzNlPdFuOVQZiR1/3ZTFjw== X-Received: by 2002:a05:620a:4708:b0:915:3be9:1160 with SMTP id af79cd13be357-9158a6bb43fmr659953785a.21.1780501574350; Wed, 03 Jun 2026 08:46:14 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a3bf5f9sm274596385a.35.2026.06.03.08.46.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:46:13 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 11/13] selftests/liveupdate: Test session and file limit removal Date: Wed, 3 Jun 2026 15:44:00 +0000 Message-ID: <20260603154402.468928-12-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With the removal of static limits on the number of sessions and files per session, the orchestrator now uses dynamic allocation. Add new test cases to verify that the system can handle a large number of sessions and files. These tests ensure that the dynamic block allocation and reuse logic for session metadata and outgoing files work correctly beyond the previous static limits. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- .../testing/selftests/liveupdate/liveupdate.c | 75 +++++++++++++++++++ .../selftests/liveupdate/luo_test_utils.c | 24 ++++++ .../selftests/liveupdate/luo_test_utils.h | 2 + 3 files changed, 101 insertions(+) diff --git a/tools/testing/selftests/liveupdate/liveupdate.c b/tools/testin= g/selftests/liveupdate/liveupdate.c index c7d94b9181e1..502fb3567e38 100644 --- a/tools/testing/selftests/liveupdate/liveupdate.c +++ b/tools/testing/selftests/liveupdate/liveupdate.c @@ -26,6 +26,7 @@ =20 #include =20 +#include "luo_test_utils.h" #include "../kselftest.h" #include "../kselftest_harness.h" =20 @@ -499,4 +500,78 @@ TEST_F(liveupdate_device, get_session_name_max_length) ASSERT_EQ(close(session_fd), 0); } =20 +/* + * Test Case: Manage Many Sessions + * + * Verifies that a large number of sessions can be created and then + * destroyed during normal system operation. This specifically tests the + * dynamic block allocation and reuse logic for session metadata management + * without preserving any files. + */ +TEST_F(liveupdate_device, preserve_many_sessions) +{ +#define MANY_SESSIONS 2000 + int session_fds[MANY_SESSIONS]; + int ret, i; + + self->fd1 =3D open(LIVEUPDATE_DEV, O_RDWR); + if (self->fd1 < 0 && errno =3D=3D ENOENT) + SKIP(return, "%s does not exist", LIVEUPDATE_DEV); + ASSERT_GE(self->fd1, 0); + + ret =3D luo_ensure_nofile_limit(MANY_SESSIONS); + if (ret =3D=3D -EPERM) + SKIP(return, "Insufficient privileges to set RLIMIT_NOFILE"); + ASSERT_EQ(ret, 0); + + for (i =3D 0; i < MANY_SESSIONS; i++) { + char name[64]; + + snprintf(name, sizeof(name), "many-session-%d", i); + session_fds[i] =3D create_session(self->fd1, name); + ASSERT_GE(session_fds[i], 0); + } + + for (i =3D 0; i < MANY_SESSIONS; i++) + ASSERT_EQ(close(session_fds[i]), 0); +} + +/* + * Test Case: Preserve Many Files + * + * Verifies that a large number of files can be preserved in a single sess= ion + * and then destroyed during normal system operation. This tests the dynam= ic + * block allocation and management for outgoing files. + */ +TEST_F(liveupdate_device, preserve_many_files) +{ +#define MANY_FILES 500 + int mem_fds[MANY_FILES]; + int session_fd, ret, i; + + self->fd1 =3D open(LIVEUPDATE_DEV, O_RDWR); + if (self->fd1 < 0 && errno =3D=3D ENOENT) + SKIP(return, "%s does not exist", LIVEUPDATE_DEV); + ASSERT_GE(self->fd1, 0); + + session_fd =3D create_session(self->fd1, "many-files-test"); + ASSERT_GE(session_fd, 0); + + ret =3D luo_ensure_nofile_limit(MANY_FILES + 10); + if (ret =3D=3D -EPERM) + SKIP(return, "Insufficient privileges to set RLIMIT_NOFILE"); + ASSERT_EQ(ret, 0); + + for (i =3D 0; i < MANY_FILES; i++) { + mem_fds[i] =3D memfd_create("test-memfd", 0); + ASSERT_GE(mem_fds[i], 0); + ASSERT_EQ(preserve_fd(session_fd, mem_fds[i], i), 0); + } + + for (i =3D 0; i < MANY_FILES; i++) + ASSERT_EQ(close(mem_fds[i]), 0); + + ASSERT_EQ(close(session_fd), 0); +} + TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.c b/tools/te= sting/selftests/liveupdate/luo_test_utils.c index 3c8721c505df..333a3530051b 100644 --- a/tools/testing/selftests/liveupdate/luo_test_utils.c +++ b/tools/testing/selftests/liveupdate/luo_test_utils.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,29 @@ int luo_open_device(void) return open(LUO_DEVICE, O_RDWR); } =20 +int luo_ensure_nofile_limit(long min_limit) +{ + struct rlimit hl; + + /* Allow to extra files to be used by test itself */ + min_limit +=3D 32; + + if (getrlimit(RLIMIT_NOFILE, &hl) < 0) + return -errno; + + if (hl.rlim_cur >=3D min_limit) + return 0; + + hl.rlim_cur =3D min_limit; + if (hl.rlim_cur > hl.rlim_max) + hl.rlim_max =3D hl.rlim_cur; + + if (setrlimit(RLIMIT_NOFILE, &hl) < 0) + return -errno; + + return 0; +} + int luo_create_session(int luo_fd, const char *name) { struct liveupdate_ioctl_create_session arg =3D { .size =3D sizeof(arg) }; diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.h b/tools/te= sting/selftests/liveupdate/luo_test_utils.h index 90099bf49577..6a0d85386613 100644 --- a/tools/testing/selftests/liveupdate/luo_test_utils.h +++ b/tools/testing/selftests/liveupdate/luo_test_utils.h @@ -26,6 +26,8 @@ int luo_create_session(int luo_fd, const char *name); int luo_retrieve_session(int luo_fd, const char *name); int luo_session_finish(int session_fd); =20 +int luo_ensure_nofile_limit(long min_limit); + int create_and_preserve_memfd(int session_fd, int token, const char *data); int restore_and_verify_memfd(int session_fd, int token, const char *expect= ed_data); =20 --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-vs1-f45.google.com (mail-vs1-f45.google.com [209.85.217.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B06013D9DB9 for ; Wed, 3 Jun 2026 15:46:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.217.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501594; cv=none; b=PYl1RBD69VPzJDiWFxb+ZAiLCj7w0bhPwWonWCmVrSbogy4J2plrxIK/Yl5nPvY8PWEu8kL5+sQfoA7TBGkBfEtAl5M74L4IHrgNr++btYpYHfGao057CNpq+VyrbgI6TTiqnds4ZUBCBAynelr3Dp+C5V46H8yeqw1D7EX24j0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501594; c=relaxed/simple; bh=zVenBMcmRxURhVBZmDsLf2LabKQiVm7GKN1LU8rMyS8=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=os+LgypyFrdRymqDu8P7b1cV0yn+vuOThAWOdKSi3tCyanLF3IwbzPoXJOQX+PPpnHJ2hPzF0Fj8/Lz+eYxTnwfnkUk+BPHyjcpsc6Qyy+dUeDKzYdUOZs2Pkr+tuKdfIVYp4ma48jJKqwJ3egvntFv5yn4XnUL+0kQ/n9bIQQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=XbsuCauu; arc=none smtp.client-ip=209.85.217.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="XbsuCauu" Received: by mail-vs1-f45.google.com with SMTP id ada2fe7eead31-6c3154fa46dso1772621137.0 for ; Wed, 03 Jun 2026 08:46:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501586; x=1781106386; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=psMAwGaqe9xuyJY3Mn283ARVP/GQQXmgr+1HpWpGRKs=; b=XbsuCauuxhUW2rofUghnExSOhGM8R9+KaB+rD9m3h+1tIQ/I3oAsajcDYcBb2cs9b/ Pd0u8pUVP/ZdMgN3pugL3F3iXL7IYG2jxv/qAMBUtBkRo2zSGPiI/URBnRBESV0Lp14c Mt4CXvH+Gj61ct0t064jV33ZtDOfiyHOodhsE+PMbeMHQlhP34vYgWaCMJiOCSWcXLXW Zv7+KkJ7gh2VJU6cJzXJvMRZ3WAorXhgR4oFeklfCI4gyWSjG+1WYDWG+90ojf93nGFM CfaD0EIF4SI32aYlEHXzXtHgV8HkLqEQ5iEHYVeISwfGWKzHCJh29t5Uge7XuL6WRREF zJlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501586; x=1781106386; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=psMAwGaqe9xuyJY3Mn283ARVP/GQQXmgr+1HpWpGRKs=; b=gbay/b8kRcNKAH7kWqz6aFpGYY/P/UGjqzNoaWu5OE41OLTSHtBJjQ/HcKK2ZnZ41B Mkqr9uqRfq7C7IacTW7gP69+L+VWnl1BmGH5GggZ0P4kkUJaTocHf+/NtpLzvo9yS+xL iYs148otcFkC2wH8mwLvpWVeF5gvh9G592gNfbSfg2i7FEQnxxh6w5u5YZPzxhhtxkSC CEsr+KpGJOqU3xBm3WUrgpUui4JCqw8psSVkyFQDu0HxaNW9nj43d3eZTXnSzCbtgoEC Gag+0pMMQJWjLuAGXTAycy+SIDEAjQudfU6A69rMaMSeA5mMC0nlIsf8/8pNemXkCd7r 2uXg== X-Forwarded-Encrypted: i=1; AFNElJ/ejgo6Nj6Iq0g59HM+MPNwJ9071wh1KZ4n6MPnU5UWbIf6UF1Yc8lzQvAS1os+F8we7pGVWKaOMDYNSro=@vger.kernel.org X-Gm-Message-State: AOJu0YzpcShAWQjLspz/iZ+QtY2XOii3XYOY2kHsP7UNqzxUveZHfnWz /+4L4eVfmB2qq90DSyX6oVyAK4QnbNrCaGvP5FWy1qtSdKC4ZX6jFFWMe/NEffJze8Y= X-Gm-Gg: Acq92OEHLlNVUNaQJvcGwILnLR8YKnpp4B3Kh7OJlODP4n2sSfzqqStolMedjCzvMDe EdJF4lv8HgmLV+F26BhtSvdMb6sZ1Qb+K2BOa4pHNq1+BmMmuxomN4MXdmgEPeSDjyrnRY9GBX2 XUcmmqlZstz2N7e+JF8sXZyFQb54iua9E7/aCYJkrqRSx+FAP0hHOmxog7LFaGW+ATqM3Prn2xr DAZ5SLneqVjum3KgatJmYsuZ+SpDWRZEL2aMhujDf4xa7yYbFePVfSu+Hun0SO5M8jjhz5maVZp vq2vifQVfMYwdwpcC1C9LpIWWdg4QWMrU1kpEM06TwUah//hhAVGQuZaf8HP724vdBh4AHzgupR 5HAIYE40Mq5KIG4WNl7bSiWSzg+i4a9qh/8MFTMPvkNfY7xhByqm5mfXg3lBXltWZG+IjjBBf0U Nwzpga6AkuXxEcX8+pi9Q4hXW3fdBbchMJrRVDcqIGvH46K7l4preBlYrSGWEOEg== X-Received: by 2002:a05:6102:e0a:b0:631:2a80:e492 with SMTP id ada2fe7eead31-6ec4ce590b0mr2408029137.30.1780501586216; Wed, 03 Jun 2026 08:46:26 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8cecd053032sm23998326d6.24.2026.06.03.08.46.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:46:25 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 12/13] selftests/liveupdate: Add stress-sessions kexec test Date: Wed, 3 Jun 2026 15:44:01 +0000 Message-ID: <20260603154402.468928-13-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new test that creates 2000 LUO sessions before a kexec reboot and verifies their presence after the reboot. This ensures that the linked-block serialization mechanism works correctly for a large number of sessions. Acked-by: Mike Rapoport (Microsoft) Reviewed-by: Pratyush Yadav (Google) Signed-off-by: Pasha Tatashin --- tools/testing/selftests/liveupdate/Makefile | 1 + .../liveupdate/luo_stress_sessions.c | 102 ++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 tools/testing/selftests/liveupdate/luo_stress_sessions.c diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/se= lftests/liveupdate/Makefile index 080754787ede..ed7534468386 100644 --- a/tools/testing/selftests/liveupdate/Makefile +++ b/tools/testing/selftests/liveupdate/Makefile @@ -6,6 +6,7 @@ TEST_GEN_PROGS +=3D liveupdate =20 TEST_GEN_PROGS_EXTENDED +=3D luo_kexec_simple TEST_GEN_PROGS_EXTENDED +=3D luo_multi_session +TEST_GEN_PROGS_EXTENDED +=3D luo_stress_sessions =20 TEST_FILES +=3D do_kexec.sh =20 diff --git a/tools/testing/selftests/liveupdate/luo_stress_sessions.c b/too= ls/testing/selftests/liveupdate/luo_stress_sessions.c new file mode 100644 index 000000000000..f201b1839d1d --- /dev/null +++ b/tools/testing/selftests/liveupdate/luo_stress_sessions.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright (c) 2026, Google LLC. + * Pasha Tatashin + * + * Validate that LUO can handle a large number of sessions across a kexec + * reboot. + */ + +#include +#include +#include "luo_test_utils.h" + +#define NUM_SESSIONS 2000 +#define STATE_SESSION_NAME "kexec_many_state" +#define STATE_MEMFD_TOKEN 999 + +/* Stage 1: Executed before the kexec reboot. */ +static void run_stage_1(int luo_fd) +{ + int ret, i; + + ksft_print_msg("[STAGE 1] Increasing ulimit for open files...\n"); + ret =3D luo_ensure_nofile_limit(NUM_SESSIONS); + if (ret =3D=3D -EPERM) + ksft_exit_skip("Insufficient privileges to set RLIMIT_NOFILE\n"); + if (ret < 0) + ksft_exit_fail_msg("luo_ensure_nofile_limit failed: %s\n", strerror(-ret= )); + + ksft_print_msg("[STAGE 1] Creating state file for next stage (2)...\n"); + create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2); + + ksft_print_msg("[STAGE 1] Creating %d sessions...\n", NUM_SESSIONS); + + for (i =3D 0; i < NUM_SESSIONS; i++) { + char name[LIVEUPDATE_SESSION_NAME_LENGTH]; + int s_fd; + + snprintf(name, sizeof(name), "many-test-%d", i); + s_fd =3D luo_create_session(luo_fd, name); + if (s_fd < 0) { + fail_exit("luo_create_session for '%s' at index %d", + name, i); + } + } + + ksft_print_msg("[STAGE 1] Successfully created %d sessions.\n", + NUM_SESSIONS); + + close(luo_fd); + daemonize_and_wait(); +} + +/* Stage 2: Executed after the kexec reboot. */ +static void run_stage_2(int luo_fd, int state_session_fd) +{ + int i, stage; + + ksft_print_msg("[STAGE 2] Starting post-kexec verification...\n"); + + restore_and_read_stage(state_session_fd, STATE_MEMFD_TOKEN, &stage); + if (stage !=3D 2) { + fail_exit("Expected stage 2, but state file contains %d", + stage); + } + + ksft_print_msg("[STAGE 2] Retrieving and finishing %d sessions...\n", + NUM_SESSIONS); + + for (i =3D 0; i < NUM_SESSIONS; i++) { + char name[LIVEUPDATE_SESSION_NAME_LENGTH]; + int s_fd; + + snprintf(name, sizeof(name), "many-test-%d", i); + s_fd =3D luo_retrieve_session(luo_fd, name); + if (s_fd < 0) { + fail_exit("luo_retrieve_session for '%s' at index %d", + name, i); + } + + if (luo_session_finish(s_fd) < 0) { + fail_exit("luo_session_finish for '%s' at index %d", + name, i); + } + close(s_fd); + } + + ksft_print_msg("[STAGE 2] Finalizing state session...\n"); + if (luo_session_finish(state_session_fd) < 0) + fail_exit("luo_session_finish for state session"); + close(state_session_fd); + + ksft_print_msg("\n--- MANY-SESSIONS KEXEC TEST PASSED (%d sessions) ---\n= ", + NUM_SESSIONS); +} + +int main(int argc, char *argv[]) +{ + return luo_test(argc, argv, STATE_SESSION_NAME, + run_stage_1, run_stage_2); +} --=20 2.53.0 From nobody Mon Jun 8 04:26:41 2026 Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 42C263DD513 for ; Wed, 3 Jun 2026 15:46:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501602; cv=none; b=kO6H/cMYSw8gB9/9cfXugSD02Rd/TAIhf1XAK4mCAXVtryW5S2hvMizp07QisOyM+L2CWoEf6JXtw65TpJ+8prP+FgctzpoUzP0roCfhz7EZPngeNAW6wdyck1Px1Iq/tpdvD5erHg0e95UHEziPoUEek9/N1lk89JYid0ZY5/E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780501602; c=relaxed/simple; bh=PI26M0khAE7StCXBHeuwdUicbhLFrZpiZfsokDq9n88=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f17rSsUUktECFgyaqKnClLDTr6yNoTCiA863h6xTvJ+7Oc0LUFaih9uujIywGX9FcE6us6KPfC6TXwP0x/klc6rXGAh0gYTjm451Z4oYBxJv/xT7/mauKW6HQrWldtrZcQqBQvqllFPwERlxNW0ZkwGwodKI6S3Yh/VSl6vOKdI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=UfnMU9x4; arc=none smtp.client-ip=209.85.219.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="UfnMU9x4" Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-8cceaacd07bso54075666d6.3 for ; Wed, 03 Jun 2026 08:46:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1780501598; x=1781106398; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=LZ44uuKaEudMkx03Nujcoh6Uuv+6Qpcd4aVYSw8wkq4=; b=UfnMU9x4HQ5qiHtFUE0lTFss8h/kLwIwM83j9GbTZhGvGXszQl8tr6XSAJY1tNAKlw Qj1G0CU3SJrnxCoUmRu6p7idE7BGqb7YKlchkUMwVRnw22z0d3QESJuxbP2ypf/u77vu RBvxBD8885JZf9GhT7X8H8WnQ9637cQIUNDlKvfzngK72pRBy4fryDXVv2hyEAWtFRU1 IAtQfDrX0YGSZr2BHgW1t9gddbSUofKjyl1DfIKKugoWQKu+u5q1PH+I5USpNtniWECr oF7XJ71VAo2DubK9lgqpW4u2pNUm2egb5BUI4CgGO0oiKgUzKBv2WZ/HRQowF0u0snfs EnXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780501598; x=1781106398; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=LZ44uuKaEudMkx03Nujcoh6Uuv+6Qpcd4aVYSw8wkq4=; b=mjpqbIxVLniDSJywPAdXN8G6f1W0CivHRF2QAMXmoqvkAkh+yUyV1xgV2774FEbcZn gJdjwAQ8aDOp8RxmltgD3f+XqSilegdCSPIVBP8x8PZ7Zm9yjRPa+z6tcJH2gOabuw5t QK86Z8/DKr+7PPRoLZ1UzpZhxxsk/ufUJm7zudLd3N0OqPyuo/l+yVfNuuUM7XXou4h8 SjztJt1mzrIomycSPJ/aGlDTAU7baCyXWhxFdswcYp9OkD4cAU8IecIHuQTlE345ler9 6Z3e2sTq+Hp/EeU193JH0WF4CZ3y4JvjYyLIE1zPGSMd+styrL+aJKgfq3b23VJu+RZk 09BA== X-Forwarded-Encrypted: i=1; AFNElJ9W6mWXPdvXSZEY5Y1KXca8zvm3bpv7hTNryv9e5f352unJF1TGK0dQlwcn6sSOjflJPcEM+k3Pm9sWhYo=@vger.kernel.org X-Gm-Message-State: AOJu0YyOooWv5TvuXyUZa4Q2YBNzbaWzOhUtIor6XBWTuVrkjNo8VMeo QHirfKIUPvjTOnU04Fju1UCKCBY270fUmxkY9BGp+y8vM168BzDLUKnCegW871WNdGo= X-Gm-Gg: Acq92OEbi3OSBtV6dhKwcHzNWPEMLEqHN+K+5llxVbdMvJG1uRgUH9HHw7sbbcAnz8x rj8g9tgF6Im1qm8x8YKRfLdTSY3V2tPI3plmDV7nTFoA4Dtl2+lP3vFNfwaaDntz+bSyYEIkf3u kugTgmJMZrAX/0Caxw+3ZsceRvBvAS7/ATKmf/9cr/dMUQfKufmFmDd+dp0H5y6+FlqOLoWsRp0 GffDw4XkJ/yAkZw+E57olE8PE0oba6U8Zsns6V31BfaTMrptckGLXMqEoahtUA7H6NSwkJimtvc yD4Da5JUpDGN8lznkecDuJ0vimbJ3Jqo1aj/wer2Q/bZEBrwuQBiPZUYJwM1HrATIOM8vcGGybc i7VwX0yFSWMB++HRbE+E7Q+FBuXhhoiEsgu+MQtDctScYl/hRY2ixPpGMmbMsxEA3xc5HCjZjSC sTtoUyWEQ9QS0w3abvXqJ8mjFp4vlaeri9as7sujvFsKkvqT1yDupaSwv4wwmdZKKTDMoGgeaO X-Received: by 2002:a05:6214:dce:b0:8ac:a6bd:503b with SMTP id 6a1803df08f44-8cecde9c8admr53195506d6.15.1780501598131; Wed, 03 Jun 2026 08:46:38 -0700 (PDT) Received: from plex ([71.181.43.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8cecd277070sm22665326d6.48.2026.06.03.08.46.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 08:46:37 -0700 (PDT) From: Pasha Tatashin To: linux-kselftest@vger.kernel.org, rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org, skhan@linuxfoundation.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, corbet@lwn.net, pasha.tatashin@soleen.com, dmatlack@google.com, kexec@lists.infradead.org, pratyush@kernel.org, skhawaja@google.com, graf@amazon.com Subject: [PATCH v7 13/13] selftests/liveupdate: Add stress-files kexec test Date: Wed, 3 Jun 2026 15:44:02 +0000 Message-ID: <20260603154402.468928-14-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260603154402.468928-1-pasha.tatashin@soleen.com> References: <20260603154402.468928-1-pasha.tatashin@soleen.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new luo_stress_files kexec test that verifies preserving and retrieving 500 files across a kexec reboot. Reviewed-by: Pratyush Yadav (Google) Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Pasha Tatashin --- tools/testing/selftests/liveupdate/Makefile | 1 + .../selftests/liveupdate/luo_stress_files.c | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 tools/testing/selftests/liveupdate/luo_stress_files.c diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/se= lftests/liveupdate/Makefile index ed7534468386..30689d22cb02 100644 --- a/tools/testing/selftests/liveupdate/Makefile +++ b/tools/testing/selftests/liveupdate/Makefile @@ -7,6 +7,7 @@ TEST_GEN_PROGS +=3D liveupdate TEST_GEN_PROGS_EXTENDED +=3D luo_kexec_simple TEST_GEN_PROGS_EXTENDED +=3D luo_multi_session TEST_GEN_PROGS_EXTENDED +=3D luo_stress_sessions +TEST_GEN_PROGS_EXTENDED +=3D luo_stress_files =20 TEST_FILES +=3D do_kexec.sh =20 diff --git a/tools/testing/selftests/liveupdate/luo_stress_files.c b/tools/= testing/selftests/liveupdate/luo_stress_files.c new file mode 100644 index 000000000000..0cdf9cd4bac7 --- /dev/null +++ b/tools/testing/selftests/liveupdate/luo_stress_files.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright (c) 2026, Google LLC. + * Pasha Tatashin + * + * Validate that LUO can handle a large number of files per session across + * a kexec reboot. + */ + +#include +#include +#include "luo_test_utils.h" + +#define NUM_FILES 500 +#define STATE_SESSION_NAME "kexec_many_files_state" +#define STATE_MEMFD_TOKEN 9999 +#define TEST_SESSION_NAME "many_files_session" + +/* Stage 1: Executed before the kexec reboot. */ +static void run_stage_1(int luo_fd) +{ + int session_fd, i; + + ksft_print_msg("[STAGE 1] Creating state file for next stage (2)...\n"); + create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2); + + ksft_print_msg("[STAGE 1] Creating test session '%s'...\n", TEST_SESSION_= NAME); + session_fd =3D luo_create_session(luo_fd, TEST_SESSION_NAME); + if (session_fd < 0) + fail_exit("luo_create_session"); + + ksft_print_msg("[STAGE 1] Preserving %d files...\n", NUM_FILES); + for (i =3D 0; i < NUM_FILES; i++) { + char data[64]; + + snprintf(data, sizeof(data), "file-data-%d", i); + if (create_and_preserve_memfd(session_fd, i, data) < 0) + fail_exit("create_and_preserve_memfd for index %d", i); + } + + ksft_print_msg("[STAGE 1] Successfully preserved %d files.\n", NUM_FILES); + + close(luo_fd); + daemonize_and_wait(); +} + +/* Stage 2: Executed after the kexec reboot. */ +static void run_stage_2(int luo_fd, int state_session_fd) +{ + int session_fd; + int i, stage; + + ksft_print_msg("[STAGE 2] Starting post-kexec verification...\n"); + + restore_and_read_stage(state_session_fd, STATE_MEMFD_TOKEN, &stage); + if (stage !=3D 2) { + fail_exit("Expected stage 2, but state file contains %d", + stage); + } + + ksft_print_msg("[STAGE 2] Retrieving test session '%s'...\n", TEST_SESSIO= N_NAME); + session_fd =3D luo_retrieve_session(luo_fd, TEST_SESSION_NAME); + if (session_fd < 0) + fail_exit("luo_retrieve_session"); + + ksft_print_msg("[STAGE 2] Verifying %d files...\n", NUM_FILES); + for (i =3D 0; i < NUM_FILES; i++) { + char data[64]; + int fd; + + snprintf(data, sizeof(data), "file-data-%d", i); + fd =3D restore_and_verify_memfd(session_fd, i, data); + if (fd < 0) + fail_exit("restore_and_verify_memfd for index %d", i); + close(fd); + } + + ksft_print_msg("[STAGE 2] Finishing test session...\n"); + if (luo_session_finish(session_fd) < 0) + fail_exit("luo_session_finish for test session"); + close(session_fd); + + ksft_print_msg("[STAGE 2] Finalizing state session...\n"); + if (luo_session_finish(state_session_fd) < 0) + fail_exit("luo_session_finish for state session"); + close(state_session_fd); + + ksft_print_msg("\n--- MANY-FILES KEXEC TEST PASSED (%d files) ---\n", + NUM_FILES); +} + +int main(int argc, char *argv[]) +{ + return luo_test(argc, argv, STATE_SESSION_NAME, + run_stage_1, run_stage_2); +} --=20 2.53.0