From nobody Mon Feb 9 23:16:06 2026 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (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 EEC4137474D for ; Tue, 3 Feb 2026 22:09:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770156598; cv=none; b=mqHiik5+gwtRc7KjJr0JBLIKD6t0cO2ocDOmOS/dxz+8Dy2fQ+4IzgxxFoFv5NeS3dzSra5RQYTz+qo5t2t/YLJT8Rpj0K2HzGMUQYpV38+FmWaydBiD+A8Qceaza+SJ+MfCFcPAonDjk71zlp6EbAb0lLeivxADUhAY7jHUcbE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770156598; c=relaxed/simple; bh=U2NeIRFaQ3Zq0bn+PGdbije6ufeaFsRzIb+El2Dmm70=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=SKwfx4W1l6a/LmC+JBPPWpGFgIC7qjVzY9WIiP83D5s7pDGNkM758qf3Ea7J9jrIJqu5GYsXaZn/3ooWuzlfGtDIbc59HeIlneheDkjlbgWZ8RjILPNBZiHQBRWs/PzkPNVhxwpquelFdSQ+27Hu87U5sd1u24SmeeSXceCeVwg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--skhawaja.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=X7SDxHg1; arc=none smtp.client-ip=209.85.215.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--skhawaja.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="X7SDxHg1" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b6ce1b57b9cso3316009a12.1 for ; Tue, 03 Feb 2026 14:09:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770156595; x=1770761395; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7JJwhexRKvGqKj8BmK4wLoDK8FPsWDJ7kCbEwN39qlQ=; b=X7SDxHg1hJz1i1K7/DGmt3D3V53aYOQ+7PoUFFv7giIT7gIphjv9b2zDeC1alQyfgp WfmeIIka5TQk7PzXmr2m7z1UlVxHkX+YoXbQQ8WBSxNNc6Wjege7+lVhf0vUwNRjedp3 0YevDou1ye9dVBobaIn0YMtLSI4QERzhgbbB+BcqAEFb3YJkzV1va5JHSWp75jW7HQ93 fT4A58apSzJsf48eQn3AWjr9UfxVvh/xxnj5zqaf5cgf8zTeYt3HGj5UnbmGY5p3c6kU dfBy5C0m1BtU/6LLU/6iDupzCLYb9v0abGSGxkqps0QuKZhSJJuA8zYC33lA8MOi02Bk 01sw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770156595; x=1770761395; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7JJwhexRKvGqKj8BmK4wLoDK8FPsWDJ7kCbEwN39qlQ=; b=j57Aoekr5YcS66l4bxbOfclpFqMkvR0Kv2DwYpqiPvhR4imh57bHEx1jc16xjXw5oV luhoMP9nbGgFNLM6ao26cUPp+XRJK3uKA8qcRGQct4mKpmrpGuEn/6Z+mrB3ltXYWpaF lLfVQszzA35vGi+LnEZibR7N+Up7vyB561k/JrlSdZ1lupEu6+U9y2yLs+Dz58B9S2W4 N5QMu4ct9Ixh2v5DiP61ORspOZDOKn769vH/+ibsn7vlgTEvhKWzpA9x8dS00eQf8kI1 KWQQ/x1jixHREMc3heyiGY8MV6eWFoyrOnMmNxDAKGZv1CyPSmYn7HQ7mOeCQywBGsme oF8A== X-Forwarded-Encrypted: i=1; AJvYcCVwFVJvJavxWzWuu0m9IKb/mtVmjMz46oVfBO4oFCCBac8yua5CZ6jLhuw6Flt2EdJlQzCB4uNBwD14KE8=@vger.kernel.org X-Gm-Message-State: AOJu0Ywnj7MOHKrpgi/aIkt5VT59tovqu2zft+5U5D0mqKcTV/mIERah xwxPBNVbfLhdvJreVK/oV6GTB/fwZ62dPLXmD9bDcfBYCCmAYVr3+238Pz3DAq6JBZnCOx/PUaJ Tm5fr+Cqjl1XGKg== X-Received: from pgbdv5.prod.google.com ([2002:a05:6a02:4465:b0:c65:e24e:cef1]) (user=skhawaja job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:6b85:b0:364:be7:6ffc with SMTP id adf61e73a8af0-393720db58dmr925648637.18.1770156595253; Tue, 03 Feb 2026 14:09:55 -0800 (PST) Date: Tue, 3 Feb 2026 22:09:37 +0000 In-Reply-To: <20260203220948.2176157-1-skhawaja@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203220948.2176157-1-skhawaja@google.com> X-Mailer: git-send-email 2.53.0.rc2.204.g2597b5adb4-goog Message-ID: <20260203220948.2176157-4-skhawaja@google.com> Subject: [PATCH 03/14] liveupdate: luo_file: Add internal APIs for file preservation From: Samiullah Khawaja To: David Woodhouse , Lu Baolu , Joerg Roedel , Will Deacon , Jason Gunthorpe Cc: Pasha Tatashin , Robin Murphy , Kevin Tian , Alex Williamson , Shuah Khan , iommu@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Saeed Mahameed , Adithya Jayachandran , Parav Pandit , Leon Romanovsky , William Tu , Samiullah Khawaja , Pratyush Yadav , David Matlack , Andrew Morton , Chris Li , Pranjal Shrivastava , Vipin Sharma , YiFei Zhu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pasha Tatashin The core liveupdate mechanism allows userspace to preserve file descriptors. However, kernel subsystems often manage struct file objects directly and need to participate in the preservation process programmatically without relying solely on userspace interaction. Signed-off-by: Pasha Tatashin --- include/linux/liveupdate.h | 21 ++++++++++ kernel/liveupdate/luo_file.c | 71 ++++++++++++++++++++++++++++++++ kernel/liveupdate/luo_internal.h | 16 +++++++ 3 files changed, 108 insertions(+) diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h index fe82a6c3005f..8e47504ba01e 100644 --- a/include/linux/liveupdate.h +++ b/include/linux/liveupdate.h @@ -23,6 +23,7 @@ struct file; /** * struct liveupdate_file_op_args - Arguments for file operation callbacks. * @handler: The file handler being called. + * @session: The session this file belongs to. * @retrieved: The retrieve status for the 'can_finish / finish' * operation. * @file: The file object. For retrieve: [OUT] The callback se= ts @@ -40,6 +41,7 @@ struct file; */ struct liveupdate_file_op_args { struct liveupdate_file_handler *handler; + struct liveupdate_session *session; bool retrieved; struct file *file; u64 serialized_data; @@ -234,6 +236,13 @@ int liveupdate_unregister_flb(struct liveupdate_file_h= andler *fh, =20 int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp); int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp); +/* kernel can internally retrieve files */ +int liveupdate_get_file_incoming(struct liveupdate_session *s, u64 token, + struct file **filep); + +/* Get a token for an outgoing file, or -ENOENT if file is not preserved */ +int liveupdate_get_token_outgoing(struct liveupdate_session *s, + struct file *file, u64 *tokenp); =20 #else /* CONFIG_LIVEUPDATE */ =20 @@ -281,5 +290,17 @@ static inline int liveupdate_flb_get_outgoing(struct l= iveupdate_flb *flb, return -EOPNOTSUPP; } =20 +static inline int liveupdate_get_file_incoming(struct liveupdate_session *= s, + u64 token, struct file **filep) +{ + return -EOPNOTSUPP; +} + +static inline int liveupdate_get_token_outgoing(struct liveupdate_session = *s, + struct file *file, u64 *tokenp) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_LIVEUPDATE */ #endif /* _LINUX_LIVEUPDATE_H */ diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c index 32759e846bc9..7ac591542059 100644 --- a/kernel/liveupdate/luo_file.c +++ b/kernel/liveupdate/luo_file.c @@ -302,6 +302,7 @@ int luo_preserve_file(struct luo_file_set *file_set, u6= 4 token, int fd) mutex_init(&luo_file->mutex); =20 args.handler =3D fh; + args.session =3D luo_session_from_file_set(file_set); args.file =3D file; err =3D fh->ops->preserve(&args); if (err) @@ -355,6 +356,7 @@ void luo_file_unpreserve_files(struct luo_file_set *fil= e_set) struct luo_file, list); =20 args.handler =3D luo_file->fh; + args.session =3D luo_session_from_file_set(file_set); args.file =3D luo_file->file; args.serialized_data =3D luo_file->serialized_data; args.private_data =3D luo_file->private_data; @@ -383,6 +385,7 @@ static int luo_file_freeze_one(struct luo_file_set *fil= e_set, struct liveupdate_file_op_args args =3D {0}; =20 args.handler =3D luo_file->fh; + args.session =3D luo_session_from_file_set(file_set); args.file =3D luo_file->file; args.serialized_data =3D luo_file->serialized_data; args.private_data =3D luo_file->private_data; @@ -404,6 +407,7 @@ static void luo_file_unfreeze_one(struct luo_file_set *= file_set, struct liveupdate_file_op_args args =3D {0}; =20 args.handler =3D luo_file->fh; + args.session =3D luo_session_from_file_set(file_set); args.file =3D luo_file->file; args.serialized_data =3D luo_file->serialized_data; args.private_data =3D luo_file->private_data; @@ -590,6 +594,7 @@ int luo_retrieve_file(struct luo_file_set *file_set, u6= 4 token, } =20 args.handler =3D luo_file->fh; + args.session =3D luo_session_from_file_set(file_set); args.serialized_data =3D luo_file->serialized_data; err =3D luo_file->fh->ops->retrieve(&args); if (!err) { @@ -615,6 +620,7 @@ static int luo_file_can_finish_one(struct luo_file_set = *file_set, struct liveupdate_file_op_args args =3D {0}; =20 args.handler =3D luo_file->fh; + args.session =3D luo_session_from_file_set(file_set); args.file =3D luo_file->file; args.serialized_data =3D luo_file->serialized_data; args.retrieved =3D luo_file->retrieved; @@ -632,6 +638,7 @@ static void luo_file_finish_one(struct luo_file_set *fi= le_set, guard(mutex)(&luo_file->mutex); =20 args.handler =3D luo_file->fh; + args.session =3D luo_session_from_file_set(file_set); args.file =3D luo_file->file; args.serialized_data =3D luo_file->serialized_data; args.retrieved =3D luo_file->retrieved; @@ -919,3 +926,67 @@ int liveupdate_unregister_file_handler(struct liveupda= te_file_handler *fh) return err; } EXPORT_SYMBOL_GPL(liveupdate_unregister_file_handler); + +/** + * liveupdate_get_token_outgoing - Get the token for a preserved file. + * @s: The outgoing liveupdate session. + * @file: The file object to search for. + * @tokenp: Output parameter for the found token. + * + * Searches the list of preserved files in an outgoing session for a match= ing + * file object. If found, the corresponding user-provided token is returne= d. + * + * This function is intended for in-kernel callers that need to correlate a + * file with its liveupdate token. + * + * Context: Can be called from any context that can acquire the session mu= tex. + * Return: 0 on success, -ENOENT if the file is not preserved in this sess= ion. + */ +int liveupdate_get_token_outgoing(struct liveupdate_session *s, + struct file *file, u64 *tokenp) +{ + struct luo_file_set *file_set =3D luo_file_set_from_session(s); + struct luo_file *luo_file; + int err =3D -ENOENT; + + list_for_each_entry(luo_file, &file_set->files_list, list) { + if (luo_file->file =3D=3D file) { + if (tokenp) + *tokenp =3D luo_file->token; + err =3D 0; + break; + } + } + + return err; +} + +/** + * liveupdate_get_file_incoming - Retrieves a preserved file for in-kernel= use. + * @s: The incoming liveupdate session (restored from the previous ke= rnel). + * @token: The unique token identifying the file to retrieve. + * @filep: On success, this will be populated with a pointer to the retri= eved + * 'struct file'. + * + * Provides a kernel-internal API for other subsystems to retrieve their + * preserved files after a live update. This function is a simple wrapper + * around luo_retrieve_file(), allowing callers to find a file by its toke= n. + * + * The operation is idempotent; subsequent calls for the same token will r= eturn + * a pointer to the same 'struct file' object. + * + * The caller receives a new reference to the file and must call fput() wh= en it + * is no longer needed. The file's lifetime is managed by LUO and any user= space + * file descriptors. If the caller needs to hold a reference to the file b= eyond + * the immediate scope, it must call get_file() itself. + * + * Context: Can be called from any context in the new kernel that has a ha= ndle + * to a restored session. + * Return: 0 on success. Returns -ENOENT if no file with the matching toke= n is + * found, or any other negative errno on failure. + */ +int liveupdate_get_file_incoming(struct liveupdate_session *s, u64 token, + struct file **filep) +{ + return luo_retrieve_file(luo_file_set_from_session(s), token, filep); +} diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_inter= nal.h index 8083d8739b09..a24933d24fd9 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -77,6 +77,22 @@ struct luo_session { struct mutex mutex; }; =20 +static inline struct liveupdate_session *luo_session_from_file_set(struct = luo_file_set *file_set) +{ + struct luo_session *session; + + session =3D container_of(file_set, struct luo_session, file_set); + + return (struct liveupdate_session *)session; +} + +static inline struct luo_file_set *luo_file_set_from_session(struct liveup= date_session *s) +{ + struct luo_session *session =3D (struct luo_session *)s; + + return &session->file_set; +} + 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); --=20 2.53.0.rc2.204.g2597b5adb4-goog