2023-07-05 14:09:13

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 2/2] btrfs: fix 64-bit division link failure

From: Arnd Bergmann <[email protected]>

Some of the recent refactoring of the statfs code apparently
brought back a link failure on older gcc versions that I had
fixed before:

arm-linux-gnueabi-ld: fs/btrfs/super.o: in function `btrfs_statfs':
super.c:(.text+0xec40): undefined reference to `__aeabi_uldivmod'

I think what happened is that gcc is free to not inline a function
despite the 'inline' annotation, and when this happens it can end
up partially inlining the div_u64() helper in a way that breaks the
__builtin_constant_p() based optimization.

I only see this behavior for gcc-9, but it's possible that the same
thing happens in later versions as well when the code changes again.

Change this to __always_inline to prevent it from happening again,
and add a comment about this.

Fixes: 7e17916b35797 ("btrfs: avoid link error with CONFIG_NO_AUTO_INLINE")
Signed-off-by: Arnd Bergmann <[email protected]>
---
fs/btrfs/super.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index f1dd172d8d5bd..7c8ee0da0f0d1 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1902,9 +1902,9 @@ static inline void btrfs_descending_sort_devices(

/*
* The helper to calc the free space on the devices that can be used to store
- * file data.
+ * file data, always inline to avoid a link failure with gcc-9 and earlier.
*/
-static inline int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info,
+static __always_inline int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info,
u64 *free_bytes)
{
struct btrfs_device_info *devices_info;
--
2.39.2



2023-07-10 17:28:41

by David Sterba

[permalink] [raw]
Subject: Re: [PATCH 2/2] btrfs: fix 64-bit division link failure

On Wed, Jul 05, 2023 at 04:01:09PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <[email protected]>
>
> Some of the recent refactoring of the statfs code apparently
> brought back a link failure on older gcc versions that I had
> fixed before:
>
> arm-linux-gnueabi-ld: fs/btrfs/super.o: in function `btrfs_statfs':
> super.c:(.text+0xec40): undefined reference to `__aeabi_uldivmod'
>
> I think what happened is that gcc is free to not inline a function
> despite the 'inline' annotation, and when this happens it can end
> up partially inlining the div_u64() helper in a way that breaks the
> __builtin_constant_p() based optimization.
>
> I only see this behavior for gcc-9, but it's possible that the same
> thing happens in later versions as well when the code changes again.

This is second fix to work around compiler assumptions and dependency
from other code, somehow this feels like the fix is being done in the
wrong place. Filesystem code using a number division helpers that are
supposed to abstract away 64bit division problems are as far as we
should go. Speculating about partial inlining or working/not-working
constant value detection maybe belongs to some highly optimized code but
not to a plain API usage.