On 13/09/2019 01:55, Zygo Blaxell wrote:
> Currently, the command:
> 
>       btrfs balance start -dconvert=single,soft .
> 
> on a Raspberry Pi produces the following kernel message:
> 
>       BTRFS error (device mmcblk0p2): balance: invalid convert data profile 
> single
> 
> This fails because we use is_power_of_2(unsigned long) to validate
> the new data profile, the constant for 'single' profile uses bit 48,
> and there are only 32 bits in a long on ARM.
> 
> Fix by open-coding the check using u64 variables.
> 
> Tested by completing the original balance command on several Raspberry
> Pis.
> 
> Signed-off-by: Zygo Blaxell <ce3g8...@umail.furryterror.org>
> ---
>  fs/btrfs/volumes.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 88a323a453d8..252c6049c6b7 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -3906,7 +3906,11 @@ static int alloc_profile_is_valid(u64 flags, int 
> extended)
>               return !extended; /* "0" is valid for usual profiles */
>  
>       /* true if exactly one bit set */
> -     return is_power_of_2(flags);
> +     /*
> +      * Don't use is_power_of_2(unsigned long) because it won't work
> +      * for the single profile (1ULL << 48) on 32-bit CPUs.
> +      */
> +     return flags != 0 && (flags & (flags - 1)) == 0;

Would
flags && IS_ALIGNED(flags)

Work as well? IS_ALIGNED() should be type-save due to the typeof():
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)

Or maybe I'm missing something subtle?

Thanks,
        Johannes
-- 
Johannes Thumshirn                            SUSE Labs Filesystems
jthumsh...@suse.de                                +49 911 74053 689
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5
90409 Nürnberg
Germany
(HRB 247165, AG München)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

Reply via email to