From: "Luis Claudio R. Goncalves" <lgoncalv@redhat.com>
To: Prashant Singh <singhpra@juniper.net>
Cc: Ard Biesheuvel <ardb@kernel.org>, Jeremy Kerr <jk@ozlabs.org>,
linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org,
Jonathan Corbet <corbet@lwn.net>,
linux-doc@vger.kernel.org,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Clark Williams <clrkwllms@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
linux-rt-devel@lists.linux.dev
Subject: Re: [PATCH v2] efivarfs: add nostatfs mount option to skip QueryVariableInfo()
Date: Thu, 24 Sep 2026 08:05:34 -0300 [thread overview]
Message-ID: <arUD_p0Vn4qyBH_e@redhat.com> (raw)
In-Reply-To: <20260919044124.8268-1-singhpra@juniper.net>
On Fri, Sep 18, 2026 at 09:41:24PM -0700, Prashant Singh wrote:
> QueryVariableInfo() is an EFI runtime service that, on some firmware,
> takes tens of milliseconds and runs with preemption disabled, stalling
> the CPU that services it. efivarfs_statfs() calls it (rate-limited since
> commit b2326338dc68 ("efivarfs: Rate limit statfs() handler")) to report
> the variable-store used/available capacity, so any statfs(2) -- e.g.
> every "df" -- can inject that stall into unrelated latency-sensitive
> workloads on the same CPU.
>
> Add a "nostatfs" mount option: when set, statfs(2) skips
> QueryVariableInfo() entirely and reports zero used/available. It is set
> by default on CONFIG_PREEMPT_RT so real-time kernels do not take the
> stall out of the box.
I tested the patch and was quite satisfied with the results, but upon a
comment from colleagues I ran a few more tests and noticed (confirmed their
hunch) that fwupd complains about not being able to get the free space in
efivars:
# fwupdmgr get-devices | grep efivars
│ Update Error: getting efivars free space is not supported
│ │ Update Error: getting efivars free space is not supported
...
I was not able to establish whether that would prevent specific operations
due to the HW I had available for such test.
One idea that I have been musing over is whether or not it would be interesting
to create a static view of the efivars statfs data when first mounting it
and updating this data whenever efivars is modified (create/write/delete).
Does that sound reasonable?
Luis
> Tested on an Intel Xeon E5-2628L v4, 6.12 kernel with CONFIG_PREEMPT_RT
> not set (so reporting defaults to enabled and nostatfs must be passed
> explicitly), via "strace -T -e trace=statfs df" on the efivarfs mount.
>
> Default mount: statfs() calls QueryVariableInfo() and returns the real
> store capacity, ~66-129 ms per call:
>
> statfs("/sys/firmware/efi/efivars", {f_type=EFIVARFS_MAGIC,
> f_bsize=1, f_blocks=90024, f_bfree=33387, f_bavail=28267, ...})
> = 0 <0.129124>
>
> With -o nostatfs: no firmware call, capacity reported as zero, ~11 us per
> call:
>
> statfs("/sys/firmware/efi/efivars", {f_type=EFIVARFS_MAGIC,
> f_bsize=1, f_blocks=0, f_bfree=0, f_bavail=0, ...}) = 0 <0.000011>
>
> Signed-off-by: Prashant Singh <singhpra@juniper.net>
> ---
> Changes since v1:
> - Per review, dropped the fs.efivarfs sysctl / cached-capacity approach
> entirely; instead add a simple "nostatfs" mount option that skips
> QueryVariableInfo() in statfs() and reports zero, set by default on
> CONFIG_PREEMPT_RT.
>
> v1: https://lore.kernel.org/all/20260917071600.5587-1-singhpra@juniper.net/
>
> Documentation/filesystems/efivarfs.rst | 10 ++++++++++
> fs/efivarfs/internal.h | 1 +
> fs/efivarfs/super.c | 20 +++++++++++++++++---
> 3 files changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/filesystems/efivarfs.rst b/Documentation/filesystems/efivarfs.rst
> index f646c3f0980f..3ead638c796a 100644
> --- a/Documentation/filesystems/efivarfs.rst
> +++ b/Documentation/filesystems/efivarfs.rst
> @@ -37,6 +37,16 @@ accidentally.
> |4_bytes_of_attributes + efivar_data|
> +-----------------------------------+
>
> +Mount options
> +=============
> +
> +nostatfs
> + Do not report the variable-store used/available capacity in
> + ``statfs(2)``; report zero instead. Obtaining the capacity requires the
> + ``QueryVariableInfo()`` EFI runtime service, which on some firmware takes
> + tens of milliseconds and runs with preemption disabled, stalling the
> + calling CPU. This option is set by default on ``CONFIG_PREEMPT_RT``.
> +
> *See also:*
>
> - Documentation/admin-guide/acpi/ssdt-overlays.rst
> diff --git a/fs/efivarfs/internal.h b/fs/efivarfs/internal.h
> index f913b6824289..0cb053884b4b 100644
> --- a/fs/efivarfs/internal.h
> +++ b/fs/efivarfs/internal.h
> @@ -11,6 +11,7 @@
> struct efivarfs_mount_opts {
> kuid_t uid;
> kgid_t gid;
> + bool nostatfs; /* skip QueryVariableInfo() in statfs() */
> };
>
> struct efivarfs_fs_info {
> diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
> index 8d33f11db2a1..fbdaa4915d30 100644
> --- a/fs/efivarfs/super.c
> +++ b/fs/efivarfs/super.c
> @@ -74,6 +74,8 @@ static int efivarfs_show_options(struct seq_file *m, struct dentry *root)
> if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
> seq_printf(m, ",gid=%u",
> from_kgid_munged(&init_user_ns, opts->gid));
> + if (opts->nostatfs)
> + seq_puts(m, ",nostatfs");
> return 0;
> }
>
> @@ -82,13 +84,19 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
> const u32 attr = EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS |
> EFI_VARIABLE_RUNTIME_ACCESS;
> + struct efivarfs_fs_info *sfi = dentry->d_sb->s_fs_info;
> u64 storage_space, remaining_space, max_variable_size;
> u64 id = huge_encode_dev(dentry->d_sb->s_dev);
> efi_status_t status;
>
> - /* Some UEFI firmware does not implement QueryVariableInfo() */
> + /*
> + * Some UEFI firmware does not implement QueryVariableInfo(); the
> + * nostatfs mount option also disables this (preempt-disabled,
> + * potentially slow) call entirely, reporting zero used/available.
> + */
> storage_space = remaining_space = 0;
> - if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) {
> + if (!sfi->mount_opts.nostatfs &&
> + efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) {
> static DEFINE_RATELIMIT_STATE(_rs, 2 * HZ, 5);
> static u64 storage, remaining;
> static DEFINE_SPINLOCK(lock);
> @@ -323,12 +331,13 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
> }
>
> enum {
> - Opt_uid, Opt_gid,
> + Opt_uid, Opt_gid, Opt_nostatfs,
> };
>
> static const struct fs_parameter_spec efivarfs_parameters[] = {
> fsparam_uid("uid", Opt_uid),
> fsparam_gid("gid", Opt_gid),
> + fsparam_flag("nostatfs", Opt_nostatfs),
> {},
> };
>
> @@ -350,6 +359,9 @@ static int efivarfs_parse_param(struct fs_context *fc, struct fs_parameter *para
> case Opt_gid:
> opts->gid = result.gid;
> break;
> + case Opt_nostatfs:
> + opts->nostatfs = true;
> + break;
> default:
> return -EINVAL;
> }
> @@ -526,6 +538,8 @@ static int efivarfs_init_fs_context(struct fs_context *fc)
>
> sfi->mount_opts.uid = GLOBAL_ROOT_UID;
> sfi->mount_opts.gid = GLOBAL_ROOT_GID;
> + /* QueryVariableInfo() stalls the CPU; default nostatfs on PREEMPT_RT. */
> + sfi->mount_opts.nostatfs = IS_ENABLED(CONFIG_PREEMPT_RT);
>
> fc->s_fs_info = sfi;
> fc->ops = &efivarfs_context_ops;
>
> base-commit: 9b87fdc9af2fbfcdb5c24a64139685ef80f6573f
> --
> 2.34.1
>
>
---end quoted text---
next prev parent reply other threads:[~2026-09-24 11:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-19 4:41 [PATCH v2] efivarfs: add nostatfs mount option to skip QueryVariableInfo() Prashant Singh
2026-09-19 4:50 ` sashiko-bot
2026-09-19 14:51 ` Ard Biesheuvel
2026-09-24 10:56 ` Ard Biesheuvel
2026-09-24 11:05 ` Luis Claudio R. Goncalves [this message]
2026-09-24 11:12 ` Ard Biesheuvel
2026-09-24 11:19 ` Steve McIntyre
2026-09-24 11:36 ` Luis Claudio R. Goncalves
2026-09-24 11:59 ` Ard Biesheuvel
2026-09-25 1:45 ` Prashant Singh
2026-09-25 6:14 ` Sebastian Andrzej Siewior
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=arUD_p0Vn4qyBH_e@redhat.com \
--to=lgoncalv@redhat.com \
--cc=ardb@kernel.org \
--cc=bigeasy@linutronix.de \
--cc=clrkwllms@kernel.org \
--cc=corbet@lwn.net \
--cc=jk@ozlabs.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=rostedt@goodmis.org \
--cc=singhpra@juniper.net \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.