* [PATCH v2 2/3] drm_buddy: fix power-of-2 rounding errs
2026-08-30 10:33 [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions David Gow
@ 2026-08-30 10:33 ` David Gow
2026-08-30 10:58 ` sashiko-bot
2026-08-30 10:33 ` [PATCH v2 3/3] fs:btrfs: Use the new global is_power_of_2_u64() helper David Gow
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: David Gow @ 2026-08-30 10:33 UTC (permalink / raw)
To: Jim Cromie, Maciej W . Rozycki, Andrew Morton, Matthew Auld,
Arun Pravin, Joel Fernandes, David Airlie, Simona Vetter
Cc: dri-devel, linux-kernel, David Gow
From: Jim Cromie <jim.cromie@gmail.com>
The standard roundup_pow_of_two() and rounddown_pow_of_two() macros use
unsigned long internally, which on 32-bit architectures (like arm32) is
a 32-bit type.
drm_test_buddy_alloc_exceeds_max_order() uses these on a u64 value,
where they silently truncate the 10GB allocation, giving unexpected
success in DRM-CI. (see below the snip).
Fix this by replacing the those macros with the safe 64-bit power-of-two
equivalents added in the previous patch.
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Link: https://lore.kernel.org/all/20260326185413.1205870-40-jim.cromie@gmail.com/
Signed-off-by: David Gow <david@davidgow.net>
---
This should actually be version 13 or 14, I think, as it's just a rebase
of v12 here, where it was part of a large series of fixups:
https://lore.kernel.org/all/20260326185413.1205870-40-jim.cromie@gmail.com/
There are probably some other places where this is not perfectly 32-bit safe,
but this is at least enough to fix the KUnit tests.
The major changes since that version are:
- Add the helper functions rounddown_pow_of_two_u64() and
roundup_pow_of_two_u64() (see patch 1) instead of open-coding them
- Rebase now that the buddy allocator lives in drivers/gpu/buddy.c
instead of drivers/gpu/drm/drm_buddy.c
This is still breaking the gpu_test_buddy_alloc_exceeds_max_order
KUnit test on 32-bit systems:
[09:01:26] # gpu_test_buddy_alloc_exceeds_max_order: EXPECTATION FAILED at drivers/gpu/tests/gpu_buddy_test.c:1429
[09:01:26] Expected err == -22, but
[09:01:26] err == 0 (0x0)
[09:01:26] WARNING: drivers/gpu/buddy.c:508 at gpu_buddy_fini+0x244/0x2e0, CPU#0: kunit_try_catch/1595
[09:01:26] # gpu_test_buddy_alloc_exceeds_max_order: drivers/gpu/buddy.c:508: gpu_buddy_assert(gpu_buddy_block_is_free(mm->roots[i]))
[09:01:26] WARNING: drivers/gpu/buddy.c:516 at gpu_buddy_fini+0x284/0x2e0, CPU#0: kunit_try_catch/1595
[09:01:26] # gpu_test_buddy_alloc_exceeds_max_order: drivers/gpu/buddy.c:508: gpu_buddy_assert(gpu_buddy_block_is_free(mm->roots[i]))
[09:01:26] WARNING: drivers/gpu/buddy.c:516 at gpu_buddy_fini+0x284/0x2e0, CPU#0: kunit_try_catch/1595
[09:01:26] # gpu_test_buddy_alloc_exceeds_max_order: drivers/gpu/buddy.c:519: gpu_buddy_assert(!mm->used_scoreboard[i])
[09:01:26] [FAILED] gpu_test_buddy_alloc_exceeds_max_order
Changes since v1:
https://lore.kernel.org/all/20260821091918.1902032-2-david@ingeniumdigital.com/
- Rename round{up,down}_pow_of_two64() -> round{up,down_pow_of_two_u64()
(This seems nicer and more consistent with what everyone else is doing)
---
drivers/gpu/buddy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
index a5553fcec28c..0c432719f8f1 100644
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -1193,7 +1193,7 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
u64 modify_size;
int err;
- modify_size = rounddown_pow_of_two(size);
+ modify_size = rounddown_pow_of_two_u64(size);
order = ilog2(modify_size) - ilog2(mm->chunk_size);
if (order == 0)
return -ENOSPC;
@@ -1440,7 +1440,7 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
/* Roundup the size to power of 2 */
if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
- size = roundup_pow_of_two(size);
+ size = roundup_pow_of_two_u64(size);
min_block_size = size;
/*
* Normalize the requested size to min_block_size for regular allocations.
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 2/3] drm_buddy: fix power-of-2 rounding errs
2026-08-30 10:33 ` [PATCH v2 2/3] drm_buddy: fix power-of-2 rounding errs David Gow
@ 2026-08-30 10:58 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-30 10:58 UTC (permalink / raw)
To: David Gow; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Silent 32-bit truncation of u64 variables in is_power_of_2() checks.
- [Medium] The patch incompletely fixes 32-bit truncation of `u64 size` by leaving `unsigned long pages`, `fls()`, and `BIT()` in the exact same calculation paths.
--
commit c788807ff6acd696c6d8c9760009db4310c73ca2
Author: Jim Cromie <jim.cromie@gmail.com>
Subject: drm_buddy: fix power-of-2 rounding errs
This commit fixes 32-bit truncation of 64-bit sizes when using the standard
roundup_pow_of_two() and rounddown_pow_of_two() macros. It replaces them with
safe 64-bit equivalents to resolve unexpected test successes in DRM-CI on
32-bit systems.
Link: https://lore.kernel.org/all/20260326185413.1205870-40-jim.cromie@gmail.com/
> diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
> index a5553fcec28c2..0c432719f8f17 100644
> --- a/drivers/gpu/buddy.c
> +++ b/drivers/gpu/buddy.c
[ ... ]
> @@ -1440,7 +1440,7 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
>
> /* Roundup the size to power of 2 */
> if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
> - size = roundup_pow_of_two(size);
> + size = roundup_pow_of_two_u64(size);
[Severity: High]
This is a pre-existing issue, but does is_power_of_2() also suffer from the
exact same silent 32-bit truncation?
Earlier in gpu_buddy_alloc_blocks(), the 64-bit min_block_size is validated:
if (!is_power_of_2(min_block_size))
return -EINVAL;
Since is_power_of_2() expects an unsigned long, if a 64-bit value is provided
where the lower 32 bits form a power of two but the upper bits are non-zero
(e.g., 0x100001000), it seems it will be truncated to a valid power of two on
32-bit architectures. This would bypass validation and corrupt the allocator
state.
Other places doing this check on 64-bit variables:
- gpu_buddy_init() validates the 64-bit chunk_size
- gpu_buddy_can_offset_align() validates the 64-bit size
[Severity: Medium]
This is also a pre-existing issue, but does this function incompletely fix
the truncation of size by leaving 32-bit types in the subsequent
calculations?
Just below this hunk in gpu_buddy_alloc_blocks(), pages is calculated:
unsigned long pages;
...
pages = size >> ilog2(mm->chunk_size);
order = fls(pages) - 1;
Since pages is an unsigned long, it will be silently truncated if the shifted
value exceeds 32 bits on 32-bit architectures.
Additionally, on 64-bit architectures where pages is 64-bit, the fls() macro
takes a 32-bit unsigned int. If pages > 0xFFFFFFFF, fls() only sees the
lower 32 bits, which may be 0, incorrectly setting order to -1.
Further down in the allocation loop, the BIT() macro is used:
pages -= BIT(order);
If order >= 32, the BIT() macro will overflow and evaluate incorrectly. Could
these paths lead to incorrect block allocations or memory corruption for very
large sizes?
> min_block_size = size;
> /*
> * Normalize the requested size to min_block_size for regular allocations.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260830103321.2042968-1-david@davidgow.net?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] fs:btrfs: Use the new global is_power_of_2_u64() helper
2026-08-30 10:33 [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions David Gow
2026-08-30 10:33 ` [PATCH v2 2/3] drm_buddy: fix power-of-2 rounding errs David Gow
@ 2026-08-30 10:33 ` David Gow
2026-08-31 18:46 ` David Sterba
2026-08-30 10:47 ` [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions sashiko-bot
2026-08-30 11:43 ` David Laight
3 siblings, 1 reply; 7+ messages in thread
From: David Gow @ 2026-08-30 10:33 UTC (permalink / raw)
To: Jim Cromie, Maciej W . Rozycki, Andrew Morton, Matthew Auld,
Arun Pravin, Joel Fernandes, David Airlie, Simona Vetter,
Chris Mason, David Sterba
Cc: David Gow, dri-devel, linux-btrfs, linux-kernel
btrfs currently provides its own 64-bit safe version of
is_power_of_2(), in order to handle 64-bit values on 32-bit systems.
Since other subsystems also have similar helpers, a new implementation
has been added to linux/log2.h. Use this instead of the btrfs-specific
one.
Signed-off-by: David Gow <david@davidgow.net>
---
This basically just replaces a btrfs helper with the version in patch 1.
It probably doesn't make sense for this series to go in via the btrfs
tree, so it's probably worth either accepting the posssibility for a
conflict, or sending this patch in separately after the first one lands.
Cheers,
-- David
[This patch was introduced in v2 of the series.]
---
fs/btrfs/misc.h | 7 +------
fs/btrfs/zoned.c | 2 +-
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/fs/btrfs/misc.h b/fs/btrfs/misc.h
index 802060943180..e8be78341dc0 100644
--- a/fs/btrfs/misc.h
+++ b/fs/btrfs/misc.h
@@ -110,15 +110,10 @@ static inline u64 mult_perc(u64 num, u32 percent)
{
return div_u64(num * percent, 100);
}
-/* Copy of is_power_of_two that is 64bit safe */
-static inline bool is_power_of_two_u64(u64 n)
-{
- return n != 0 && (n & (n - 1)) == 0;
-}
static inline bool has_single_bit_set(u64 n)
{
- return is_power_of_two_u64(n);
+ return is_power_of_2_u64(n);
}
/*
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index a016cb471beb..b90ac4ff71b8 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -421,7 +421,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
zone_sectors = bdev_zone_sectors(bdev);
}
- ASSERT(is_power_of_two_u64(zone_sectors));
+ ASSERT(is_power_of_2_u64(zone_sectors));
zone_info->zone_size = zone_sectors << SECTOR_SHIFT;
/* We reject devices with a zone size larger than 8GB */
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 3/3] fs:btrfs: Use the new global is_power_of_2_u64() helper
2026-08-30 10:33 ` [PATCH v2 3/3] fs:btrfs: Use the new global is_power_of_2_u64() helper David Gow
@ 2026-08-31 18:46 ` David Sterba
0 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2026-08-31 18:46 UTC (permalink / raw)
To: David Gow
Cc: Jim Cromie, Maciej W . Rozycki, Andrew Morton, Matthew Auld,
Arun Pravin, Joel Fernandes, David Airlie, Simona Vetter,
Chris Mason, David Sterba, dri-devel, linux-btrfs, linux-kernel
On Sun, Aug 30, 2026 at 06:33:17PM +0800, David Gow wrote:
> btrfs currently provides its own 64-bit safe version of
> is_power_of_2(), in order to handle 64-bit values on 32-bit systems.
>
> Since other subsystems also have similar helpers, a new implementation
> has been added to linux/log2.h. Use this instead of the btrfs-specific
> one.
>
> Signed-off-by: David Gow <david@davidgow.net>
> ---
>
> This basically just replaces a btrfs helper with the version in patch 1.
> It probably doesn't make sense for this series to go in via the btrfs
> tree, so it's probably worth either accepting the posssibility for a
> conflict, or sending this patch in separately after the first one lands.
Acked-by: David Sterba <dsterba@suse.com>
As this is library API cleanup, feel free to take it with the rest of
the series.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions
2026-08-30 10:33 [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions David Gow
2026-08-30 10:33 ` [PATCH v2 2/3] drm_buddy: fix power-of-2 rounding errs David Gow
2026-08-30 10:33 ` [PATCH v2 3/3] fs:btrfs: Use the new global is_power_of_2_u64() helper David Gow
@ 2026-08-30 10:47 ` sashiko-bot
2026-08-30 11:43 ` David Laight
3 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-30 10:47 UTC (permalink / raw)
To: David Gow; +Cc: dri-devel, dsterba
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] `__roundup_pow_of_two_u64()` computes the wrong value for `n = 1` when optimizations propagate the constant, due to misuse of `ilog2(0)`.
- [Low] Kernel-doc comment for `__rounddown_pow_of_two_u64` incorrectly uses the suffix `_64` instead of `_u64`.
--
commit 1b2e30cc48e12ee945f73271fbcb60bed282f343
Author: David Gow <david@davidgow.net>
linux/log2.h: Add 64-bit safe variants of power-of-two functions
This commit adds 64-bit safe variants of power-of-two functions which always
operate on a 64-bit value regardless of sizeof(long). It also removes a
conflicting implementation from i915.
> diff --git a/include/linux/log2.h b/include/linux/log2.h
> index e17ceb32e0c97..fc44e59f57328 100644
> --- a/include/linux/log2.h
> +++ b/include/linux/log2.h
[ ... ]
> @@ -195,6 +211,63 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
> __rounddown_pow_of_two(n) \
> )
>
> +/**
> + * __rounddown_pow_of_two_64() - round a 64-bit value down to nearest power of two
> + * @n: value to round down
> + */
> +static inline __attribute_const__
> +u64 __rounddown_pow_of_two_u64(u64 n)
[Severity: Low]
Is there a typo in the kernel-doc function name?
The comment documents __rounddown_pow_of_two_64, but the function is named
__rounddown_pow_of_two_u64. Will this cause kernel-doc warnings?
> +{
> + return 1ULL << ilog2(n);
> +}
> +
[ ... ]
> +/**
> + * __roundup_pow_of_two_u64() - round a 64-bit value up to nearest power of two
> + * @n: value to round up
> + */
> +static inline __attribute_const__
> +u64 __roundup_pow_of_two_u64(u64 n)
> +{
> + return 1ULL << (ilog2(n - 1) + 1);
> +}
[Severity: High]
Can this compute the wrong value for n = 1 if the compiler propagates the
constant after macro expansion?
If n = 1 is passed to roundup_pow_of_two_u64(n) and __builtin_constant_p(n)
evaluates to false at macro expansion time, it will fall back to calling this
inline function.
When the compiler later inlines the function and proves n = 1 via constant
propagation, it will evaluate ilog2(0).
Inside the ilog2(0) macro, __builtin_constant_p(0) evaluates to true, so it
takes the constant branch (0 < 2 ? 0 : ...), which evaluates to 0.
Would this result in 1ULL << (0 + 1) returning 2 instead of 1?
Should this use fls64(n - 1) instead, similar to how the 32-bit
__roundup_pow_of_two() uses fls_long(n - 1)?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260830103321.2042968-1-david@davidgow.net?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions
2026-08-30 10:33 [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions David Gow
` (2 preceding siblings ...)
2026-08-30 10:47 ` [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions sashiko-bot
@ 2026-08-30 11:43 ` David Laight
3 siblings, 0 replies; 7+ messages in thread
From: David Laight @ 2026-08-30 11:43 UTC (permalink / raw)
To: David Gow
Cc: Jim Cromie, Maciej W . Rozycki, Andrew Morton, Matthew Auld,
Arun Pravin, Joel Fernandes, David Airlie, Simona Vetter,
Chris Mason, David Sterba, dri-devel, linux-btrfs, linux-kernel
On Sun, 30 Aug 2026 18:33:15 +0800
David Gow <david@davidgow.net> wrote:
> The existing roundup_pow_of_two() and rounddown_pow_of_two() functions work
> on values of type unsigned long, which is 32-bit on 32-bit systems.
> Equally, is_power_of_2() operates on an unsigned long.
>
> There are several instances where 64-bit safe versions of these (which
> operate on a 64-bit value regardless of sizeof(long)) are required. Most
> particularly, some hardware (especially GPUs) have 64-bit address spaces,
> and some formats (such as filesystems) use 64-bit offsets. Some of these
> (such as i915 and btrfs) have already implemented their own 64-bit
> is_power_of_2() helpers.
>
> Add a version of these which always operate on a 64-bit value. These have
> the (unimaginative) names:
> - is_power_of_2_u64()
> - roundup_pow_of_two_u64(), and
> - rounddown_pow_of_two_u64()
> and otherwise work identically to their unsigned long counterparts.
Why not just change the definitions (back?) to #defines.
Then they can be size neutral and you don't have to guess the correct one.
You may need to use __builtin_constant_p(x <= ~0u) to select between 32 and
64 bit versions.
It is also worth checking what gcc/clang generate for the 64bit versions
on 32bit when passed a 32bit variable.
It might be that they optimise the code and avoid all the 64bit maths.
David
>
> To avoid conflicts, the i915 implementation is also removed here. The btrfs
> one (which has a different name) is replaced in a separate patch.
>
> Signed-off-by: David Gow <david@davidgow.net>
> ---
>
> This patch adds u64 helpers, and the following two use them. And v2 also
> has the i915 change to remove the conflicting implementation.
>
> So I'm not sure who best wants to take these. Ultimately it's an include/linux
> change, but it touches i915, patch 2 touches GPU/DRM, and patch 3 btrfs.
> Personally, I'm keen to get patch 2 in, as it fixes a real issue, so if taking
> 1 and 2 via DRM makes more sense, that's fine by me.
>
> Changes since v1:
> https://lore.kernel.org/all/20260821091918.1902032-1-david@ingeniumdigital.com/
> - Include is_power_of_2_u64() as well, and remove the i915 version
> (Thanks, Matthew)
> - Use _u64 as a suffix for the 64-bit versions, not just 64
> (This is a much nicer name, and matches what everone else was doing)
> - Fix some comment typos.
> - Add a third patch which removes a similar is_power_of_two_u64() helper
> from btrfs.
>
> ---
> drivers/gpu/drm/i915/i915_utils.h | 5 ---
> include/linux/log2.h | 73 +++++++++++++++++++++++++++++++
> 2 files changed, 73 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
> index ecc20e0528f4..1cec51984d8c 100644
> --- a/drivers/gpu/drm/i915/i915_utils.h
> +++ b/drivers/gpu/drm/i915/i915_utils.h
> @@ -75,11 +75,6 @@ struct drm_i915_private;
> __idx; \
> })
>
> -static inline bool is_power_of_2_u64(u64 n)
> -{
> - return (n != 0 && ((n & (n - 1)) == 0));
> -}
> -
> void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint);
> static inline void __add_taint_for_CI(unsigned int taint)
> {
> diff --git a/include/linux/log2.h b/include/linux/log2.h
> index e17ceb32e0c9..fc44e59f5732 100644
> --- a/include/linux/log2.h
> +++ b/include/linux/log2.h
> @@ -47,6 +47,22 @@ bool is_power_of_2(unsigned long n)
> return n - 1 < (n ^ (n - 1));
> }
>
> +/**
> + * is_power_of_2_u64() - check if a 64-bit value is a power of two
> + * @n: the value to check
> + *
> + * Determine whether some value is a power of two, where zero is
> + * *not* considered a power of two. Unlike is_power_of_2, this version
> + * always operates on 64-bit values, even on 32-bit architectures where
> + * long is 32-bit.
> + * Return: true if @n is a power of 2, otherwise false.
> + */
> +static __always_inline __attribute_const__
> +bool is_power_of_2_u64(u64 n)
> +{
> + return n - 1 < (n ^ (n - 1));
> +}
> +
> /**
> * __roundup_pow_of_two() - round up to nearest power of two
> * @n: value to round up
> @@ -195,6 +211,63 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
> __rounddown_pow_of_two(n) \
> )
>
> +/**
> + * __rounddown_pow_of_two_64() - round a 64-bit value down to nearest power of two
> + * @n: value to round down
> + */
> +static inline __attribute_const__
> +u64 __rounddown_pow_of_two_u64(u64 n)
> +{
> + return 1ULL << ilog2(n);
> +}
> +
> +/**
> + * rounddown_pow_of_two_u64 - round a 64-bit value down to nearest power of two
> + * @n: parameter
> + *
> + * round the given value down to the nearest power of two
> + * - this always operates on 64-bit values, even on 32-bit systems
> + * - the result is undefined when n == 0
> + * - this can be used to initialise global variables from constant data
> + */
> +#define rounddown_pow_of_two_u64(n) \
> +( \
> + __builtin_constant_p(n) ? ( \
> + ((n) == 1) ? 1ULL : \
> + (1ULL << ilog2((n))) \
> + ) : \
> + __rounddown_pow_of_two_u64(n) \
> +)
> +
> +
> +/**
> + * __roundup_pow_of_two_u64() - round a 64-bit value up to nearest power of two
> + * @n: value to round up
> + */
> +static inline __attribute_const__
> +u64 __roundup_pow_of_two_u64(u64 n)
> +{
> + return 1ULL << (ilog2(n - 1) + 1);
> +}
> +
> +/**
> + * roundup_pow_of_two_u64 - round a 64-bit value up to nearest power of two
> + * @n: parameter
> + *
> + * round the given value up to the nearest power of two
> + * - this always operates on 64-bit values, even on 32-bit systems
> + * - the result is undefined when n == 0
> + * - this can be used to initialise global variables from constant data
> + */
> +#define roundup_pow_of_two_u64(n) \
> +( \
> + __builtin_constant_p(n) ? ( \
> + ((n) == 1) ? 1ULL : \
> + (1ULL << (ilog2((n) - 1) + 1)) \
> + ) : \
> + __roundup_pow_of_two_u64(n) \
> +)
> +
> static inline __attribute_const__
> int __order_base_2(unsigned long n)
> {
^ permalink raw reply [flat|nested] 7+ messages in thread