From: Avnish Chouhan <avnish@linux.ibm.com>
To: mchang@suse.com
Cc: grub-devel@gnu.org, ngompa13@gmail.com, mlewando@redhat.com,
Daniel Kiper <daniel.kiper@oracle.com>
Subject: Re: [PATCH v4 07/12] util/grub-editenv: wire set_variables to optional fs_envblk
Date: Thu, 09 Oct 2025 14:13:00 +0530 [thread overview]
Message-ID: <639bbddae08445cb8960abe5a14b93e9@linux.ibm.com> (raw)
In-Reply-To: <mailman.8809.1759994405.1112.grub-devel@gnu.org>
On 2025-10-09 12:50, grub-devel-request@gnu.org wrote:
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
> Message: 3
> Date: Thu, 9 Oct 2025 15:18:40 +0800
> From: Michael Chang <mchang@suse.com>
> To: The development of GNU GRUB <grub-devel@gnu.org>
> Cc: Neal Gompa <ngompa13@gmail.com>, Marta Lewandowska
> <mlewando@redhat.com>
> Subject: [PATCH v4 07/12] util/grub-editenv: wire set_variables to
> optional fs_envblk
> Message-ID: <20251009071845.318828-8-mchang@suse.com>
>
> This patch changes set_variables() so that it can use an external
> environment block when one is present. The variable next_entry is
> written into the external block, env_block is treated as read only, and
> all other variables are written into the normal file based envblk.
>
> A cleanup step is added to handle cases where GRUB at runtime writes
> variables into the external block because file based updates are not
> safe on a copy on write filesystem such as Btrfs. For example, the
> savedefault command can update saved_entry, and on Btrfs GRUB will
> place
> that update in the external block instead of the file envblk. If an
> older copy remains in the external block, it would override the newer
> value from the file envblk when GRUB first loads the file and then
> applies the external block on top of it. To avoid this, whenever a
> variable is updated in the file envblk, any same named key in the
> external block is deleted.
>
> Signed-off-by: Michael Chang <mchang@suse.com>
> Reviewed-by: Neal Gompa <ngompa13@gmail.com>
> ---
> util/grub-editenv.c | 58 +++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 56 insertions(+), 2 deletions(-)
>
> diff --git a/util/grub-editenv.c b/util/grub-editenv.c
> index 42a0c63f8..beb2dd4fc 100644
> --- a/util/grub-editenv.c
> +++ b/util/grub-editenv.c
> @@ -402,12 +402,35 @@ fs_envblk_write (grub_envblk_t envblk)
> fclose (fp);
> }
>
> +struct var_lookup_ctx {
> + const char *varname;
> + bool found;
> +};
> +typedef struct var_lookup_ctx var_lookup_ctx_t;
> +
> +static int
> +var_lookup_iter (const char *varname, const char *value __attribute__
> ((unused)), void *hook_data)
> +{
> + var_lookup_ctx_t *ctx = (var_lookup_ctx_t *) hook_data;
> +
> + if (grub_strcmp (ctx->varname, varname) == 0)
> + {
> + ctx->found = true;
> + return 1;
> + }
> + return 0;
> +}
> +
> static void
> set_variables (const char *name, int argc, char *argv[])
> {
> grub_envblk_t envblk;
> + grub_envblk_t envblk_on_block = NULL;
>
> envblk = open_envblk_file (name);
> + if (fs_envblk != NULL)
> + envblk_on_block = fs_envblk->ops->open (envblk);
> +
> while (argc)
> {
> char *p;
> @@ -418,15 +441,46 @@ set_variables (const char *name, int argc, char
> *argv[])
>
> *(p++) = 0;
>
> - if (! grub_envblk_set (envblk, argv[0], p))
> - grub_util_error ("%s", _("environment block too small"));
> + if ((strcmp (argv[0], "next_entry") == 0) && envblk_on_block !=
> NULL)
> + {
> + if (grub_envblk_set (envblk_on_block, argv[0], p) == 0)
> + grub_util_error ("%s", _("environment block too small"));
> + goto next;
> + }
> +
> + if (strcmp (argv[0], "env_block") == 0)
> + {
> + grub_util_warn (_("can't set env_block as it's read-only"));
> + goto next;
> + }
> +
> + if (grub_envblk_set (envblk, argv[0], p) == 0)
> + grub_util_error ("%s", _("environment block too small"));
>
> + if (envblk_on_block != NULL)
> + {
> + var_lookup_ctx_t ctx = {
> + .varname = argv[0],
> + .found = false
> + };
> +
> + grub_envblk_iterate (envblk_on_block, &ctx, var_lookup_iter);
> + if (ctx.found == true)
> + grub_envblk_delete (envblk_on_block, argv[0]);
> + }
> + next:
> argc--;
> argv++;
> }
>
> write_envblk (name, envblk);
> grub_envblk_close (envblk);
> +
> + if (envblk_on_block != NULL)
> + {
> + fs_envblk->ops->write (envblk_on_block);
> + grub_envblk_close (envblk_on_block);
> + }
> }
>
> static void
> --
> 2.51.0
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel
next parent reply other threads:[~2025-10-09 8:43 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <mailman.8809.1759994405.1112.grub-devel@gnu.org>
2025-10-09 8:43 ` Avnish Chouhan [this message]
2025-10-14 4:37 ` [PATCH v4 07/12] util/grub-editenv: wire set_variables to optional fs_envblk Michael Chang via Grub-devel
2025-10-09 7:18 [PATCH v4 00/12] Add support for external environment block on Btrfs Michael Chang via Grub-devel
2025-10-09 7:18 ` [PATCH v4 07/12] util/grub-editenv: wire set_variables to optional fs_envblk Michael Chang via Grub-devel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=639bbddae08445cb8960abe5a14b93e9@linux.ibm.com \
--to=avnish@linux.ibm.com \
--cc=daniel.kiper@oracle.com \
--cc=grub-devel@gnu.org \
--cc=mchang@suse.com \
--cc=mlewando@redhat.com \
--cc=ngompa13@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).