* [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs
@ 2023-09-10 4:54 Heinrich Schuchardt
2023-09-10 13:08 ` Ard Biesheuvel
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Heinrich Schuchardt @ 2023-09-10 4:54 UTC (permalink / raw)
To: Jeremy Kerr, Ard Biesheuvel, Anisse Astier
Cc: linux-efi, linux-kernel, Heinrich Schuchardt
Some firmware (notably U-Boot) provides GetVariable() and
GetNextVariableName() but not QueryVariableInfo().
With commit d86ff3333cb1 ("efivarfs: expose used and total size") the
statfs syscall was broken for such firmware.
If QueryVariableInfo() does not exist or returns an error, just report the
file-system size as 0 as statfs_simple() previously did.
Fixes: d86ff3333cb1 ("efivarfs: expose used and total size")
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
---
v2:
initialize remaining_space to 0
---
fs/efivarfs/super.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index e028fafa04f3..3893aae6a9be 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -29,14 +29,9 @@ 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;
- u64 storage_space, remaining_space, max_variable_size;
+ u64 storage_space, remaining_space = 0, max_variable_size;
efi_status_t status;
- status = efivar_query_variable_info(attr, &storage_space, &remaining_space,
- &max_variable_size);
- if (status != EFI_SUCCESS)
- return efi_status_to_err(status);
-
/*
* This is not a normal filesystem, so no point in pretending it has a block
* size; we declare f_bsize to 1, so that we can then report the exact value
@@ -44,10 +39,19 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
*/
buf->f_bsize = 1;
buf->f_namelen = NAME_MAX;
- buf->f_blocks = storage_space;
- buf->f_bfree = remaining_space;
buf->f_type = dentry->d_sb->s_magic;
+ /* Some UEFI firmware does not implement QueryVariable() */
+ if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) {
+ status = efivar_query_variable_info(attr, &storage_space,
+ &remaining_space,
+ &max_variable_size);
+ if (status == EFI_SUCCESS) {
+ buf->f_blocks = storage_space;
+ buf->f_bfree = remaining_space;
+ }
+ }
+
/*
* In f_bavail we declare the free space that the kernel will allow writing
* when the storage_paranoia x86 quirk is active. To use more, users
--
2.40.1
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-10 4:54 [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs Heinrich Schuchardt @ 2023-09-10 13:08 ` Ard Biesheuvel 2023-09-10 13:54 ` Ard Biesheuvel [not found] ` <ZP4QEvhzO5cOt6lT@gpdmax> 2023-09-15 4:43 ` matoro 2 siblings, 1 reply; 12+ messages in thread From: Ard Biesheuvel @ 2023-09-10 13:08 UTC (permalink / raw) To: Heinrich Schuchardt; +Cc: Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel On Sun, 10 Sept 2023 at 06:53, Heinrich Schuchardt <heinrich.schuchardt@canonical.com> wrote: > > Some firmware (notably U-Boot) provides GetVariable() and > GetNextVariableName() but not QueryVariableInfo(). > > With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > statfs syscall was broken for such firmware. > > If QueryVariableInfo() does not exist or returns an error, just report the > file-system size as 0 as statfs_simple() previously did. > > Fixes: d86ff3333cb1 ("efivarfs: expose used and total size") > Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> > --- > v2: > initialize remaining_space to 0 Thanks for the patch, and apologies for the oversight. > --- > fs/efivarfs/super.c | 20 ++++++++++++-------- > 1 file changed, 12 insertions(+), 8 deletions(-) > > diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c > index e028fafa04f3..3893aae6a9be 100644 > --- a/fs/efivarfs/super.c > +++ b/fs/efivarfs/super.c > @@ -29,14 +29,9 @@ 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; > - u64 storage_space, remaining_space, max_variable_size; > + u64 storage_space, remaining_space = 0, max_variable_size; Shouldn't storage_space be set to 0 too? > efi_status_t status; > > - status = efivar_query_variable_info(attr, &storage_space, &remaining_space, > - &max_variable_size); > - if (status != EFI_SUCCESS) > - return efi_status_to_err(status); > - > /* > * This is not a normal filesystem, so no point in pretending it has a block > * size; we declare f_bsize to 1, so that we can then report the exact value > @@ -44,10 +39,19 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) > */ > buf->f_bsize = 1; > buf->f_namelen = NAME_MAX; > - buf->f_blocks = storage_space; > - buf->f_bfree = remaining_space; > buf->f_type = dentry->d_sb->s_magic; > > + /* Some UEFI firmware does not implement QueryVariable() */ > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > + status = efivar_query_variable_info(attr, &storage_space, > + &remaining_space, > + &max_variable_size); > + if (status == EFI_SUCCESS) { > + buf->f_blocks = storage_space; > + buf->f_bfree = remaining_space; > + } > + } > + I'd prefer not to ignore the error completely here. How about we do --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -32,10 +32,15 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) u64 storage_space, remaining_space, max_variable_size; efi_status_t status; - status = efivar_query_variable_info(attr, &storage_space, &remaining_space, - &max_variable_size); - if (status != EFI_SUCCESS) - return efi_status_to_err(status); + /* Some UEFI firmware does not implement QueryVariableInfo() */ + storage_space = remaining_space = 0; + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { + status = efivar_query_variable_info(attr, &storage_space, + &remaining_space, + &max_variable_size); + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) + return efi_status_to_err(status); + } /* * This is not a normal filesystem, so no point in pretending it has a block (no need to resend if you agree) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-10 13:08 ` Ard Biesheuvel @ 2023-09-10 13:54 ` Ard Biesheuvel 2023-09-10 17:46 ` Heinrich Schuchardt 0 siblings, 1 reply; 12+ messages in thread From: Ard Biesheuvel @ 2023-09-10 13:54 UTC (permalink / raw) To: Heinrich Schuchardt; +Cc: Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel On Sun, 10 Sept 2023 at 15:08, Ard Biesheuvel <ardb@kernel.org> wrote: > > On Sun, 10 Sept 2023 at 06:53, Heinrich Schuchardt > <heinrich.schuchardt@canonical.com> wrote: > > > > Some firmware (notably U-Boot) provides GetVariable() and > > GetNextVariableName() but not QueryVariableInfo(). > > > > With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > > statfs syscall was broken for such firmware. > > > > If QueryVariableInfo() does not exist or returns an error, just report the > > file-system size as 0 as statfs_simple() previously did. > > > > Fixes: d86ff3333cb1 ("efivarfs: expose used and total size") > > Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> > > --- > > v2: > > initialize remaining_space to 0 > > Thanks for the patch, and apologies for the oversight. > > > --- > > fs/efivarfs/super.c | 20 ++++++++++++-------- > > 1 file changed, 12 insertions(+), 8 deletions(-) > > > > diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c > > index e028fafa04f3..3893aae6a9be 100644 > > --- a/fs/efivarfs/super.c > > +++ b/fs/efivarfs/super.c > > @@ -29,14 +29,9 @@ 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; > > - u64 storage_space, remaining_space, max_variable_size; > > + u64 storage_space, remaining_space = 0, max_variable_size; > > Shouldn't storage_space be set to 0 too? > > > efi_status_t status; > > > > - status = efivar_query_variable_info(attr, &storage_space, &remaining_space, > > - &max_variable_size); > > - if (status != EFI_SUCCESS) > > - return efi_status_to_err(status); > > - > > /* > > * This is not a normal filesystem, so no point in pretending it has a block > > * size; we declare f_bsize to 1, so that we can then report the exact value > > @@ -44,10 +39,19 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) > > */ > > buf->f_bsize = 1; > > buf->f_namelen = NAME_MAX; > > - buf->f_blocks = storage_space; > > - buf->f_bfree = remaining_space; > > buf->f_type = dentry->d_sb->s_magic; > > > > + /* Some UEFI firmware does not implement QueryVariable() */ > > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > > + status = efivar_query_variable_info(attr, &storage_space, > > + &remaining_space, > > + &max_variable_size); > > + if (status == EFI_SUCCESS) { > > + buf->f_blocks = storage_space; > > + buf->f_bfree = remaining_space; > > + } > > + } > > + > > I'd prefer not to ignore the error completely here. How about we do > > --- a/fs/efivarfs/super.c > +++ b/fs/efivarfs/super.c > @@ -32,10 +32,15 @@ static int efivarfs_statfs(struct dentry *dentry, > struct kstatfs *buf) > u64 storage_space, remaining_space, max_variable_size; > efi_status_t status; > > - status = efivar_query_variable_info(attr, &storage_space, > &remaining_space, > - &max_variable_size); > - if (status != EFI_SUCCESS) > - return efi_status_to_err(status); > + /* Some UEFI firmware does not implement QueryVariableInfo() */ > + storage_space = remaining_space = 0; > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > + status = efivar_query_variable_info(attr, &storage_space, > + &remaining_space, > + &max_variable_size); > + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) > + return efi_status_to_err(status); > + } > > /* > * This is not a normal filesystem, so no point in pretending > it has a block > > (no need to resend if you agree) Actually, perhaps it would be better to simply fall back to the old logic if QueryVariableInfo is not provided: diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index e028fafa04f3..50b05f1fa974 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -30,10 +30,15 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; u64 storage_space, remaining_space, max_variable_size; - efi_status_t status; + efi_status_t status = EFI_UNSUPPORTED; + + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) + status = efivar_query_variable_info(attr, &storage_space, + &remaining_space, + &max_variable_size); + if (status == EFI_UNSUPPORTED) + return simple_statfs(dentry, buf); - status = efivar_query_variable_info(attr, &storage_space, &remaining_space, - &max_variable_size); if (status != EFI_SUCCESS) return efi_status_to_err(status); ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-10 13:54 ` Ard Biesheuvel @ 2023-09-10 17:46 ` Heinrich Schuchardt 0 siblings, 0 replies; 12+ messages in thread From: Heinrich Schuchardt @ 2023-09-10 17:46 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel On 9/10/23 15:54, Ard Biesheuvel wrote: > On Sun, 10 Sept 2023 at 15:08, Ard Biesheuvel <ardb@kernel.org> wrote: >> >> On Sun, 10 Sept 2023 at 06:53, Heinrich Schuchardt >> <heinrich.schuchardt@canonical.com> wrote: >>> >>> Some firmware (notably U-Boot) provides GetVariable() and >>> GetNextVariableName() but not QueryVariableInfo(). >>> >>> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the >>> statfs syscall was broken for such firmware. >>> >>> If QueryVariableInfo() does not exist or returns an error, just report the >>> file-system size as 0 as statfs_simple() previously did. >>> >>> Fixes: d86ff3333cb1 ("efivarfs: expose used and total size") >>> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> >>> --- >>> v2: >>> initialize remaining_space to 0 >> >> Thanks for the patch, and apologies for the oversight. >> >>> --- >>> fs/efivarfs/super.c | 20 ++++++++++++-------- >>> 1 file changed, 12 insertions(+), 8 deletions(-) >>> >>> diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c >>> index e028fafa04f3..3893aae6a9be 100644 >>> --- a/fs/efivarfs/super.c >>> +++ b/fs/efivarfs/super.c >>> @@ -29,14 +29,9 @@ 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; >>> - u64 storage_space, remaining_space, max_variable_size; >>> + u64 storage_space, remaining_space = 0, max_variable_size; >> >> Shouldn't storage_space be set to 0 too? >> >>> efi_status_t status; >>> >>> - status = efivar_query_variable_info(attr, &storage_space, &remaining_space, >>> - &max_variable_size); >>> - if (status != EFI_SUCCESS) >>> - return efi_status_to_err(status); >>> - >>> /* >>> * This is not a normal filesystem, so no point in pretending it has a block >>> * size; we declare f_bsize to 1, so that we can then report the exact value >>> @@ -44,10 +39,19 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) >>> */ >>> buf->f_bsize = 1; >>> buf->f_namelen = NAME_MAX; >>> - buf->f_blocks = storage_space; >>> - buf->f_bfree = remaining_space; >>> buf->f_type = dentry->d_sb->s_magic; >>> >>> + /* Some UEFI firmware does not implement QueryVariable() */ >>> + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { >>> + status = efivar_query_variable_info(attr, &storage_space, >>> + &remaining_space, >>> + &max_variable_size); >>> + if (status == EFI_SUCCESS) { >>> + buf->f_blocks = storage_space; >>> + buf->f_bfree = remaining_space; >>> + } >>> + } >>> + >> >> I'd prefer not to ignore the error completely here. How about we do >> >> --- a/fs/efivarfs/super.c >> +++ b/fs/efivarfs/super.c >> @@ -32,10 +32,15 @@ static int efivarfs_statfs(struct dentry *dentry, >> struct kstatfs *buf) >> u64 storage_space, remaining_space, max_variable_size; >> efi_status_t status; >> >> - status = efivar_query_variable_info(attr, &storage_space, >> &remaining_space, >> - &max_variable_size); >> - if (status != EFI_SUCCESS) >> - return efi_status_to_err(status); >> + /* Some UEFI firmware does not implement QueryVariableInfo() */ >> + storage_space = remaining_space = 0; >> + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { >> + status = efivar_query_variable_info(attr, &storage_space, >> + &remaining_space, >> + &max_variable_size); >> + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) >> + return efi_status_to_err(status); >> + } >> >> /* >> * This is not a normal filesystem, so no point in pretending >> it has a block >> >> (no need to resend if you agree) Hello Ard, thanks for reviewing. Raising an error in such a rare circumstance would be ok for me. > > Actually, perhaps it would be better to simply fall back to the old > logic if QueryVariableInfo is not provided: > > diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c > index e028fafa04f3..50b05f1fa974 100644 > --- a/fs/efivarfs/super.c > +++ b/fs/efivarfs/super.c > @@ -30,10 +30,15 @@ static int efivarfs_statfs(struct dentry *dentry, > struct kstatfs *buf) > EFI_VARIABLE_BOOTSERVICE_ACCESS | > EFI_VARIABLE_RUNTIME_ACCESS; > u64 storage_space, remaining_space, max_variable_size; > - efi_status_t status; > + efi_status_t status = EFI_UNSUPPORTED; > + > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) > + status = efivar_query_variable_info(attr, &storage_space, > + &remaining_space, > + &max_variable_size); > + if (status == EFI_UNSUPPORTED) > + return simple_statfs(dentry, buf); I would not know why the block size (buf->f_bsize) should depend on the availability of QueryVariableInfo() (1 vs PAGE_SIZE). Hence I would prefer your suggestion to just add the error handling suggested in your previous mail. Best regards Heinrich > > - status = efivar_query_variable_info(attr, &storage_space, > &remaining_space, > - &max_variable_size); > if (status != EFI_SUCCESS) > return efi_status_to_err(status); ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <ZP4QEvhzO5cOt6lT@gpdmax>]
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs [not found] ` <ZP4QEvhzO5cOt6lT@gpdmax> @ 2023-09-10 20:43 ` Heinrich Schuchardt 2023-09-11 6:45 ` Ard Biesheuvel 0 siblings, 1 reply; 12+ messages in thread From: Heinrich Schuchardt @ 2023-09-10 20:43 UTC (permalink / raw) To: Anisse Astier Cc: Jeremy Kerr, Ard Biesheuvel, Anisse Astier, linux-efi, linux-kernel, Christian Brauner On 9/10/23 20:53, Anisse Astier wrote: > Hi Heinrich, > > On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: >> Some firmware (notably U-Boot) provides GetVariable() and >> GetNextVariableName() but not QueryVariableInfo(). > > From a quick search, it seems u-boot, does support QueryVariableInfo, is > it on a given version ? > > https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 QueryVariableInfo() and SetVariable() are available before ExitBootServices(), i.e. in Linux' EFI stub. ExitBootServices() results in calling efi_variables_boot_exit_notify() which disables these services during the UEFI runtime. > >> >> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the >> statfs syscall was broken for such firmware. > > Could you be more specific ? What breaks, and what regressed ? I imagine > it could be some scripts running df, but maybe you had something else in > mind ? Some more details can be found in https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. Though EFI variables are exposed via GetVariable() and GetNextVariableName() the efivar command refuses to display variables when statfs() reports an error. > >> >> If QueryVariableInfo() does not exist or returns an error, just report the >> file-system size as 0 as statfs_simple() previously did. > > I considered doing this [2] , but we settled on returning an error > instead for clarity: > https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ > > I still think it would be a good idea if necessary. We should never break user APIs. > > On the approach, I prefer what Ard proposed, to fall back to the old > approach. I think the difference in block size could also be a good > marker that something wrong is happening: > https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ This will allow user code making assumptions based on block size: If block size > 1, assume setting variables is possible. We should really avoid this. Best regards Heinrich ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-10 20:43 ` Heinrich Schuchardt @ 2023-09-11 6:45 ` Ard Biesheuvel 2023-09-11 7:47 ` Heinrich Schuchardt 2023-09-11 8:03 ` Ilias Apalodimas 0 siblings, 2 replies; 12+ messages in thread From: Ard Biesheuvel @ 2023-09-11 6:45 UTC (permalink / raw) To: Heinrich Schuchardt Cc: Anisse Astier, Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel, Christian Brauner On Sun, 10 Sept 2023 at 22:42, Heinrich Schuchardt <heinrich.schuchardt@canonical.com> wrote: > > On 9/10/23 20:53, Anisse Astier wrote: > > Hi Heinrich, > > > > On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: > >> Some firmware (notably U-Boot) provides GetVariable() and > >> GetNextVariableName() but not QueryVariableInfo(). > > > > From a quick search, it seems u-boot, does support QueryVariableInfo, is > > it on a given version ? > > > > https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 > > QueryVariableInfo() and SetVariable() are available before > ExitBootServices(), i.e. in Linux' EFI stub. > > ExitBootServices() results in calling efi_variables_boot_exit_notify() > which disables these services during the UEFI runtime. > > > > >> > >> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > >> statfs syscall was broken for such firmware. > > > > Could you be more specific ? What breaks, and what regressed ? I imagine > > it could be some scripts running df, but maybe you had something else in > > mind ? > > Some more details can be found in > https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. > > Though EFI variables are exposed via GetVariable() and > GetNextVariableName() the efivar command refuses to display variables > when statfs() reports an error. > > > > >> > >> If QueryVariableInfo() does not exist or returns an error, just report the > >> file-system size as 0 as statfs_simple() previously did. > > > > I considered doing this [2] , but we settled on returning an error > > instead for clarity: > > https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ > > > > I still think it would be a good idea if necessary. > > We should never break user APIs. > Indeed. > > > > On the approach, I prefer what Ard proposed, to fall back to the old > > approach. I think the difference in block size could also be a good > > marker that something wrong is happening: > > https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ > > This will allow user code making assumptions based on block size: > If block size > 1, assume setting variables is possible. > > We should really avoid this. > I agree that having different block sizes depending on which code path is taken is not great. But that is the situation we are already in, given that older kernels will always report PAGE_SIZE. And actually, PAGE_SIZE does not make sense either - PAGE_SIZE could be larger than 4k on ARM for instance, so the efivarfs block size will be dependent on the page size of the kernel you happened to boot. So I think we should go with the below: --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) u64 storage_space, remaining_space, max_variable_size; efi_status_t status; - status = efivar_query_variable_info(attr, &storage_space, &remaining_space, - &max_variable_size); - if (status != EFI_SUCCESS) - return efi_status_to_err(status); + /* Some UEFI firmware does not implement QueryVariableInfo() */ + storage_space = remaining_space = 0; + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { + status = efivar_query_variable_info(attr, &storage_space, + &remaining_space, + &max_variable_size); + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) + pr_warn_ratelimited("query_variable_info() failed: 0x%lx\n", + status); + } /* * This is not a normal filesystem, so no point in pretending it has a block ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-11 6:45 ` Ard Biesheuvel @ 2023-09-11 7:47 ` Heinrich Schuchardt 2023-09-11 7:57 ` Ard Biesheuvel 2023-09-11 8:03 ` Ilias Apalodimas 1 sibling, 1 reply; 12+ messages in thread From: Heinrich Schuchardt @ 2023-09-11 7:47 UTC (permalink / raw) To: Ard Biesheuvel Cc: Anisse Astier, Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel, Christian Brauner On 9/11/23 08:45, Ard Biesheuvel wrote: > On Sun, 10 Sept 2023 at 22:42, Heinrich Schuchardt > <heinrich.schuchardt@canonical.com> wrote: >> >> On 9/10/23 20:53, Anisse Astier wrote: >>> Hi Heinrich, >>> >>> On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: >>>> Some firmware (notably U-Boot) provides GetVariable() and >>>> GetNextVariableName() but not QueryVariableInfo(). >>> >>> From a quick search, it seems u-boot, does support QueryVariableInfo, is >>> it on a given version ? >>> >>> https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 >> >> QueryVariableInfo() and SetVariable() are available before >> ExitBootServices(), i.e. in Linux' EFI stub. >> >> ExitBootServices() results in calling efi_variables_boot_exit_notify() >> which disables these services during the UEFI runtime. >> >>> >>>> >>>> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the >>>> statfs syscall was broken for such firmware. >>> >>> Could you be more specific ? What breaks, and what regressed ? I imagine >>> it could be some scripts running df, but maybe you had something else in >>> mind ? >> >> Some more details can be found in >> https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. >> >> Though EFI variables are exposed via GetVariable() and >> GetNextVariableName() the efivar command refuses to display variables >> when statfs() reports an error. >> >>> >>>> >>>> If QueryVariableInfo() does not exist or returns an error, just report the >>>> file-system size as 0 as statfs_simple() previously did. >>> >>> I considered doing this [2] , but we settled on returning an error >>> instead for clarity: >>> https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ >>> >>> I still think it would be a good idea if necessary. >> >> We should never break user APIs. >> > > Indeed. > >>> >>> On the approach, I prefer what Ard proposed, to fall back to the old >>> approach. I think the difference in block size could also be a good >>> marker that something wrong is happening: >>> https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ >> >> This will allow user code making assumptions based on block size: >> If block size > 1, assume setting variables is possible. >> >> We should really avoid this. >> > > I agree that having different block sizes depending on which code path > is taken is not great. But that is the situation we are already in, > given that older kernels will always report PAGE_SIZE. And actually, > PAGE_SIZE does not make sense either - PAGE_SIZE could be larger than > 4k on ARM for instance, so the efivarfs block size will be dependent > on the page size of the kernel you happened to boot. > > So I think we should go with the below: > > --- a/fs/efivarfs/super.c > +++ b/fs/efivarfs/super.c > @@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, > struct kstatfs *buf) > u64 storage_space, remaining_space, max_variable_size; > efi_status_t status; > > - status = efivar_query_variable_info(attr, &storage_space, > &remaining_space, > - &max_variable_size); > - if (status != EFI_SUCCESS) > - return efi_status_to_err(status); > + /* Some UEFI firmware does not implement QueryVariableInfo() */ > + storage_space = remaining_space = 0; > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > + status = efivar_query_variable_info(attr, &storage_space, > + &remaining_space, > + &max_variable_size); > + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) > + pr_warn_ratelimited("query_variable_info() > failed: 0x%lx\n", > + status); Adding a warning here is helpful. The else branch would be: + } else { + buf->f_blocks = storage_space; + buf->f_bfree = remaining_space; + } Best regards Heinrich > + } > > /* > * This is not a normal filesystem, so no point in pretending > it has a block ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-11 7:47 ` Heinrich Schuchardt @ 2023-09-11 7:57 ` Ard Biesheuvel 0 siblings, 0 replies; 12+ messages in thread From: Ard Biesheuvel @ 2023-09-11 7:57 UTC (permalink / raw) To: Heinrich Schuchardt Cc: Anisse Astier, Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel, Christian Brauner On Mon, 11 Sept 2023 at 09:46, Heinrich Schuchardt <heinrich.schuchardt@canonical.com> wrote: > > On 9/11/23 08:45, Ard Biesheuvel wrote: > > On Sun, 10 Sept 2023 at 22:42, Heinrich Schuchardt > > <heinrich.schuchardt@canonical.com> wrote: > >> > >> On 9/10/23 20:53, Anisse Astier wrote: > >>> Hi Heinrich, > >>> > >>> On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: > >>>> Some firmware (notably U-Boot) provides GetVariable() and > >>>> GetNextVariableName() but not QueryVariableInfo(). > >>> > >>> From a quick search, it seems u-boot, does support QueryVariableInfo, is > >>> it on a given version ? > >>> > >>> https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 > >> > >> QueryVariableInfo() and SetVariable() are available before > >> ExitBootServices(), i.e. in Linux' EFI stub. > >> > >> ExitBootServices() results in calling efi_variables_boot_exit_notify() > >> which disables these services during the UEFI runtime. > >> > >>> > >>>> > >>>> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > >>>> statfs syscall was broken for such firmware. > >>> > >>> Could you be more specific ? What breaks, and what regressed ? I imagine > >>> it could be some scripts running df, but maybe you had something else in > >>> mind ? > >> > >> Some more details can be found in > >> https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. > >> > >> Though EFI variables are exposed via GetVariable() and > >> GetNextVariableName() the efivar command refuses to display variables > >> when statfs() reports an error. > >> > >>> > >>>> > >>>> If QueryVariableInfo() does not exist or returns an error, just report the > >>>> file-system size as 0 as statfs_simple() previously did. > >>> > >>> I considered doing this [2] , but we settled on returning an error > >>> instead for clarity: > >>> https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ > >>> > >>> I still think it would be a good idea if necessary. > >> > >> We should never break user APIs. > >> > > > > Indeed. > > > >>> > >>> On the approach, I prefer what Ard proposed, to fall back to the old > >>> approach. I think the difference in block size could also be a good > >>> marker that something wrong is happening: > >>> https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ > >> > >> This will allow user code making assumptions based on block size: > >> If block size > 1, assume setting variables is possible. > >> > >> We should really avoid this. > >> > > > > I agree that having different block sizes depending on which code path > > is taken is not great. But that is the situation we are already in, > > given that older kernels will always report PAGE_SIZE. And actually, > > PAGE_SIZE does not make sense either - PAGE_SIZE could be larger than > > 4k on ARM for instance, so the efivarfs block size will be dependent > > on the page size of the kernel you happened to boot. > > > > So I think we should go with the below: > > > > --- a/fs/efivarfs/super.c > > +++ b/fs/efivarfs/super.c > > @@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, > > struct kstatfs *buf) > > u64 storage_space, remaining_space, max_variable_size; > > efi_status_t status; > > > > - status = efivar_query_variable_info(attr, &storage_space, > > &remaining_space, > > - &max_variable_size); > > - if (status != EFI_SUCCESS) > > - return efi_status_to_err(status); > > + /* Some UEFI firmware does not implement QueryVariableInfo() */ > > + storage_space = remaining_space = 0; > > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > > + status = efivar_query_variable_info(attr, &storage_space, > > + &remaining_space, > > + &max_variable_size); > > + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) > > + pr_warn_ratelimited("query_variable_info() > > failed: 0x%lx\n", > > + status); > > Adding a warning here is helpful. The else branch would be: > > + } else { > + buf->f_blocks = storage_space; > + buf->f_bfree = remaining_space; > + } > The else branch is redundant if we leave the assignments of f_blocks and f_bfree where they were before. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-11 6:45 ` Ard Biesheuvel 2023-09-11 7:47 ` Heinrich Schuchardt @ 2023-09-11 8:03 ` Ilias Apalodimas 2023-09-11 8:05 ` Ard Biesheuvel 1 sibling, 1 reply; 12+ messages in thread From: Ilias Apalodimas @ 2023-09-11 8:03 UTC (permalink / raw) To: Ard Biesheuvel Cc: Heinrich Schuchardt, Anisse Astier, Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel, Christian Brauner Hi Ard, On Mon, 11 Sept 2023 at 09:45, Ard Biesheuvel <ardb@kernel.org> wrote: > > On Sun, 10 Sept 2023 at 22:42, Heinrich Schuchardt > <heinrich.schuchardt@canonical.com> wrote: > > > > On 9/10/23 20:53, Anisse Astier wrote: > > > Hi Heinrich, > > > > > > On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: > > >> Some firmware (notably U-Boot) provides GetVariable() and > > >> GetNextVariableName() but not QueryVariableInfo(). > > > > > > From a quick search, it seems u-boot, does support QueryVariableInfo, is > > > it on a given version ? > > > > > > https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 > > > > QueryVariableInfo() and SetVariable() are available before > > ExitBootServices(), i.e. in Linux' EFI stub. > > > > ExitBootServices() results in calling efi_variables_boot_exit_notify() > > which disables these services during the UEFI runtime. > > > > > > > >> > > >> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > > >> statfs syscall was broken for such firmware. > > > > > > Could you be more specific ? What breaks, and what regressed ? I imagine > > > it could be some scripts running df, but maybe you had something else in > > > mind ? > > > > Some more details can be found in > > https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. > > > > Though EFI variables are exposed via GetVariable() and > > GetNextVariableName() the efivar command refuses to display variables > > when statfs() reports an error. > > > > > > > >> > > >> If QueryVariableInfo() does not exist or returns an error, just report the > > >> file-system size as 0 as statfs_simple() previously did. > > > > > > I considered doing this [2] , but we settled on returning an error > > > instead for clarity: > > > https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ > > > > > > I still think it would be a good idea if necessary. > > > > We should never break user APIs. > > > > Indeed. > > > > > > > On the approach, I prefer what Ard proposed, to fall back to the old > > > approach. I think the difference in block size could also be a good > > > marker that something wrong is happening: > > > https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ > > > > This will allow user code making assumptions based on block size: > > If block size > 1, assume setting variables is possible. > > > > We should really avoid this. > > > > I agree that having different block sizes depending on which code path > is taken is not great. But that is the situation we are already in, > given that older kernels will always report PAGE_SIZE. And actually, > PAGE_SIZE does not make sense either - PAGE_SIZE could be larger than > 4k on ARM for instance, so the efivarfs block size will be dependent > on the page size of the kernel you happened to boot. > > So I think we should go with the below: > > --- a/fs/efivarfs/super.c > +++ b/fs/efivarfs/super.c > @@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, > struct kstatfs *buf) > u64 storage_space, remaining_space, max_variable_size; > efi_status_t status; > > - status = efivar_query_variable_info(attr, &storage_space, > &remaining_space, > - &max_variable_size); > - if (status != EFI_SUCCESS) > - return efi_status_to_err(status); > + /* Some UEFI firmware does not implement QueryVariableInfo() */ > + storage_space = remaining_space = 0; > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > + status = efivar_query_variable_info(attr, &storage_space, > + &remaining_space, > + &max_variable_size); > + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) > + pr_warn_ratelimited("query_variable_info() > failed: 0x%lx\n", > + status); > + } I think this is better, but shouldn't we initialize the status variable now? Or is there more code following that I am missing? Thanks /Ilias > > /* > * This is not a normal filesystem, so no point in pretending > it has a block ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-11 8:03 ` Ilias Apalodimas @ 2023-09-11 8:05 ` Ard Biesheuvel 2023-09-11 8:14 ` Ilias Apalodimas 0 siblings, 1 reply; 12+ messages in thread From: Ard Biesheuvel @ 2023-09-11 8:05 UTC (permalink / raw) To: Ilias Apalodimas Cc: Heinrich Schuchardt, Anisse Astier, Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel, Christian Brauner On Mon, 11 Sept 2023 at 10:04, Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote: > > Hi Ard, > > On Mon, 11 Sept 2023 at 09:45, Ard Biesheuvel <ardb@kernel.org> wrote: > > > > On Sun, 10 Sept 2023 at 22:42, Heinrich Schuchardt > > <heinrich.schuchardt@canonical.com> wrote: > > > > > > On 9/10/23 20:53, Anisse Astier wrote: > > > > Hi Heinrich, > > > > > > > > On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: > > > >> Some firmware (notably U-Boot) provides GetVariable() and > > > >> GetNextVariableName() but not QueryVariableInfo(). > > > > > > > > From a quick search, it seems u-boot, does support QueryVariableInfo, is > > > > it on a given version ? > > > > > > > > https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 > > > > > > QueryVariableInfo() and SetVariable() are available before > > > ExitBootServices(), i.e. in Linux' EFI stub. > > > > > > ExitBootServices() results in calling efi_variables_boot_exit_notify() > > > which disables these services during the UEFI runtime. > > > > > > > > > > >> > > > >> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > > > >> statfs syscall was broken for such firmware. > > > > > > > > Could you be more specific ? What breaks, and what regressed ? I imagine > > > > it could be some scripts running df, but maybe you had something else in > > > > mind ? > > > > > > Some more details can be found in > > > https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. > > > > > > Though EFI variables are exposed via GetVariable() and > > > GetNextVariableName() the efivar command refuses to display variables > > > when statfs() reports an error. > > > > > > > > > > >> > > > >> If QueryVariableInfo() does not exist or returns an error, just report the > > > >> file-system size as 0 as statfs_simple() previously did. > > > > > > > > I considered doing this [2] , but we settled on returning an error > > > > instead for clarity: > > > > https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ > > > > > > > > I still think it would be a good idea if necessary. > > > > > > We should never break user APIs. > > > > > > > Indeed. > > > > > > > > > > On the approach, I prefer what Ard proposed, to fall back to the old > > > > approach. I think the difference in block size could also be a good > > > > marker that something wrong is happening: > > > > https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ > > > > > > This will allow user code making assumptions based on block size: > > > If block size > 1, assume setting variables is possible. > > > > > > We should really avoid this. > > > > > > > I agree that having different block sizes depending on which code path > > is taken is not great. But that is the situation we are already in, > > given that older kernels will always report PAGE_SIZE. And actually, > > PAGE_SIZE does not make sense either - PAGE_SIZE could be larger than > > 4k on ARM for instance, so the efivarfs block size will be dependent > > on the page size of the kernel you happened to boot. > > > > So I think we should go with the below: > > > > --- a/fs/efivarfs/super.c > > +++ b/fs/efivarfs/super.c > > @@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, > > struct kstatfs *buf) > > u64 storage_space, remaining_space, max_variable_size; > > efi_status_t status; > > > > - status = efivar_query_variable_info(attr, &storage_space, > > &remaining_space, > > - &max_variable_size); > > - if (status != EFI_SUCCESS) > > - return efi_status_to_err(status); > > + /* Some UEFI firmware does not implement QueryVariableInfo() */ > > + storage_space = remaining_space = 0; > > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > > + status = efivar_query_variable_info(attr, &storage_space, > > + &remaining_space, > > + &max_variable_size); > > + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) > > + pr_warn_ratelimited("query_variable_info() > > failed: 0x%lx\n", > > + status); > > + } > > I think this is better, but shouldn't we initialize the status > variable now? Or is there more code following that I am missing? > status is not referenced again after this. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-11 8:05 ` Ard Biesheuvel @ 2023-09-11 8:14 ` Ilias Apalodimas 0 siblings, 0 replies; 12+ messages in thread From: Ilias Apalodimas @ 2023-09-11 8:14 UTC (permalink / raw) To: Ard Biesheuvel Cc: Heinrich Schuchardt, Anisse Astier, Jeremy Kerr, Anisse Astier, linux-efi, linux-kernel, Christian Brauner On Mon, 11 Sept 2023 at 11:06, Ard Biesheuvel <ardb@kernel.org> wrote: > > On Mon, 11 Sept 2023 at 10:04, Ilias Apalodimas > <ilias.apalodimas@linaro.org> wrote: > > > > Hi Ard, > > > > On Mon, 11 Sept 2023 at 09:45, Ard Biesheuvel <ardb@kernel.org> wrote: > > > > > > On Sun, 10 Sept 2023 at 22:42, Heinrich Schuchardt > > > <heinrich.schuchardt@canonical.com> wrote: > > > > > > > > On 9/10/23 20:53, Anisse Astier wrote: > > > > > Hi Heinrich, > > > > > > > > > > On Sun, Sep 10, 2023 at 06:54:45AM +0200, Heinrich Schuchardt wrote: > > > > >> Some firmware (notably U-Boot) provides GetVariable() and > > > > >> GetNextVariableName() but not QueryVariableInfo(). > > > > > > > > > > From a quick search, it seems u-boot, does support QueryVariableInfo, is > > > > > it on a given version ? > > > > > > > > > > https://elixir.bootlin.com/u-boot/v2023.07.02/source/lib/efi_loader/efi_variable.c#L391 > > > > > > > > QueryVariableInfo() and SetVariable() are available before > > > > ExitBootServices(), i.e. in Linux' EFI stub. > > > > > > > > ExitBootServices() results in calling efi_variables_boot_exit_notify() > > > > which disables these services during the UEFI runtime. > > > > > > > > > > > > > >> > > > > >> With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > > > > >> statfs syscall was broken for such firmware. > > > > > > > > > > Could you be more specific ? What breaks, and what regressed ? I imagine > > > > > it could be some scripts running df, but maybe you had something else in > > > > > mind ? > > > > > > > > Some more details can be found in > > > > https://bugs.launchpad.net/ubuntu/+source/linux-meta-riscv/+bug/2034705. > > > > > > > > Though EFI variables are exposed via GetVariable() and > > > > GetNextVariableName() the efivar command refuses to display variables > > > > when statfs() reports an error. > > > > > > > > > > > > > >> > > > > >> If QueryVariableInfo() does not exist or returns an error, just report the > > > > >> file-system size as 0 as statfs_simple() previously did. > > > > > > > > > > I considered doing this [2] , but we settled on returning an error > > > > > instead for clarity: > > > > > https://lore.kernel.org/linux-efi/20230515-vorgaben-portrait-bb1b4255d31a@brauner/ > > > > > > > > > > I still think it would be a good idea if necessary. > > > > > > > > We should never break user APIs. > > > > > > > > > > Indeed. > > > > > > > > > > > > > On the approach, I prefer what Ard proposed, to fall back to the old > > > > > approach. I think the difference in block size could also be a good > > > > > marker that something wrong is happening: > > > > > https://lore.kernel.org/linux-efi/CAMj1kXEkNSoqG4zWfCZ8Ytte5b2SzwXggZp21Xt17Pszd-q0dg@mail.gmail.com/ > > > > > > > > This will allow user code making assumptions based on block size: > > > > If block size > 1, assume setting variables is possible. > > > > > > > > We should really avoid this. > > > > > > > > > > I agree that having different block sizes depending on which code path > > > is taken is not great. But that is the situation we are already in, > > > given that older kernels will always report PAGE_SIZE. And actually, > > > PAGE_SIZE does not make sense either - PAGE_SIZE could be larger than > > > 4k on ARM for instance, so the efivarfs block size will be dependent > > > on the page size of the kernel you happened to boot. > > > > > > So I think we should go with the below: > > > > > > --- a/fs/efivarfs/super.c > > > +++ b/fs/efivarfs/super.c > > > @@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, > > > struct kstatfs *buf) > > > u64 storage_space, remaining_space, max_variable_size; > > > efi_status_t status; > > > > > > - status = efivar_query_variable_info(attr, &storage_space, > > > &remaining_space, > > > - &max_variable_size); > > > - if (status != EFI_SUCCESS) > > > - return efi_status_to_err(status); > > > + /* Some UEFI firmware does not implement QueryVariableInfo() */ > > > + storage_space = remaining_space = 0; > > > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { > > > + status = efivar_query_variable_info(attr, &storage_space, > > > + &remaining_space, > > > + &max_variable_size); > > > + if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) > > > + pr_warn_ratelimited("query_variable_info() > > > failed: 0x%lx\n", > > > + status); > > > + } > > > > I think this is better, but shouldn't we initialize the status > > variable now? Or is there more code following that I am missing? > > > > status is not referenced again after this. Ah fair enough. I'd still initialize it for sanity, but with or without Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs 2023-09-10 4:54 [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs Heinrich Schuchardt 2023-09-10 13:08 ` Ard Biesheuvel [not found] ` <ZP4QEvhzO5cOt6lT@gpdmax> @ 2023-09-15 4:43 ` matoro 2 siblings, 0 replies; 12+ messages in thread From: matoro @ 2023-09-15 4:43 UTC (permalink / raw) To: Heinrich Schuchardt Cc: Jeremy Kerr, Ard Biesheuvel, Anisse Astier, linux-efi, linux-kernel, Linux Ia64 On 2023-09-10 00:54, Heinrich Schuchardt wrote: > Some firmware (notably U-Boot) provides GetVariable() and > GetNextVariableName() but not QueryVariableInfo(). > > With commit d86ff3333cb1 ("efivarfs: expose used and total size") the > statfs syscall was broken for such firmware. > > If QueryVariableInfo() does not exist or returns an error, just report > the > file-system size as 0 as statfs_simple() previously did. > > Fixes: d86ff3333cb1 ("efivarfs: expose used and total size") > Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> > --- > v2: > initialize remaining_space to 0 > --- > fs/efivarfs/super.c | 20 ++++++++++++-------- > 1 file changed, 12 insertions(+), 8 deletions(-) > > diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c > index e028fafa04f3..3893aae6a9be 100644 > --- a/fs/efivarfs/super.c > +++ b/fs/efivarfs/super.c > @@ -29,14 +29,9 @@ 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; > - u64 storage_space, remaining_space, max_variable_size; > + u64 storage_space, remaining_space = 0, max_variable_size; > efi_status_t status; > > - status = efivar_query_variable_info(attr, &storage_space, > &remaining_space, > - &max_variable_size); > - if (status != EFI_SUCCESS) > - return efi_status_to_err(status); > - > /* > * This is not a normal filesystem, so no point in pretending it has > a block > * size; we declare f_bsize to 1, so that we can then report the > exact value > @@ -44,10 +39,19 @@ static int efivarfs_statfs(struct dentry *dentry, > struct kstatfs *buf) > */ > buf->f_bsize = 1; > buf->f_namelen = NAME_MAX; > - buf->f_blocks = storage_space; > - buf->f_bfree = remaining_space; > buf->f_type = dentry->d_sb->s_magic; > > + /* Some UEFI firmware does not implement QueryVariable() */ > + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) > { > + status = efivar_query_variable_info(attr, &storage_space, > + &remaining_space, > + &max_variable_size); > + if (status == EFI_SUCCESS) { > + buf->f_blocks = storage_space; > + buf->f_bfree = remaining_space; > + } > + } > + > /* > * In f_bavail we declare the free space that the kernel will allow > writing > * when the storage_paranoia x86 quirk is active. To use more, users FYI, this issue/fix affects ia64 EFI implementation as well, so adding a CC. ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2023-09-15 4:59 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-10 4:54 [PATCH v2 1/1] efivarfs: fix statfs() on efivarfs Heinrich Schuchardt
2023-09-10 13:08 ` Ard Biesheuvel
2023-09-10 13:54 ` Ard Biesheuvel
2023-09-10 17:46 ` Heinrich Schuchardt
[not found] ` <ZP4QEvhzO5cOt6lT@gpdmax>
2023-09-10 20:43 ` Heinrich Schuchardt
2023-09-11 6:45 ` Ard Biesheuvel
2023-09-11 7:47 ` Heinrich Schuchardt
2023-09-11 7:57 ` Ard Biesheuvel
2023-09-11 8:03 ` Ilias Apalodimas
2023-09-11 8:05 ` Ard Biesheuvel
2023-09-11 8:14 ` Ilias Apalodimas
2023-09-15 4:43 ` matoro
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox