[dpdk-dev] [PATCH] memory: fix alignment in eal_get_virtual_area()

Burakov, Anatoly anatoly.burakov at intel.com
Mon Jul 16 16:16:46 CEST 2018


On 16-Jul-18 3:01 PM, Burakov, Anatoly wrote:
> On 16-Jul-18 2:29 PM, Stojaczyk, DariuszX wrote:
>>
>>> -----Original Message-----
>>> From: Burakov, Anatoly
>>> Sent: Monday, July 16, 2018 2:58 PM
>>> To: Stojaczyk, DariuszX <dariuszx.stojaczyk at intel.com>; dev at dpdk.org
>>> Cc: stable at dpdk.org
>>> Subject: Re: [PATCH] memory: fix alignment in eal_get_virtual_area()
>>>
>>> On 13-Jun-18 8:08 PM, Dariusz Stojaczyk wrote:
>>>> Although the alignment mechanism works as intended, the
>>>> `no_align` bool flag was set incorrectly. We were aligning
>>>> buffers that didn't need extra alignment, and weren't
>>>> aligning ones that really needed it.
>>>>
>>>> Fixes: b7cc54187ea4 ("mem: move virtual area function in common 
>>>> directory")
>>>> Cc: anatoly.burakov at intel.com
>>>> Cc: stable at dpdk.org
>>>>
>>>> Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk at intel.com>
>>>> ---
>>>>    lib/librte_eal/common/eal_common_memory.c | 2 +-
>>>>    1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/lib/librte_eal/common/eal_common_memory.c
>>> b/lib/librte_eal/common/eal_common_memory.c
>>>> index 4f0688f..a7c89f0 100644
>>>> --- a/lib/librte_eal/common/eal_common_memory.c
>>>> +++ b/lib/librte_eal/common/eal_common_memory.c
>>>> @@ -70,7 +70,7 @@ eal_get_virtual_area(void *requested_addr, size_t 
>>>> *size,
>>>>         * system page size is the same as requested page size.
>>>>         */
>>>>        no_align = (requested_addr != NULL &&
>>>> -        ((uintptr_t)requested_addr & (page_sz - 1)) == 0) ||
>>>> +        ((uintptr_t)requested_addr & (page_sz - 1))) ||
>>>>            page_sz == system_page_sz;
>>>>
>>>>        do {
>>>>
>>>
>>> This patch is wrong - no alignment should be performed if address is
>>> already alighed, e.g. if requested_addr & (page_sz - 1) == 0. The
>>> original code was correct.
>>
>> If we provide an aligned address with ADDR_IS_HINT flag and OS decides 
>> not to use it, we end up with potentially unaligned address that needs 
>> to be manually aligned and that's what this patch does. If the 
>> requested address wasn't aligned to the provided page_sz, why would we 
>> bother aligning it manually?
> 
> no_align is a flag that indicates whether we should or shouldn't align 
> the resulting end address - it is not meant to align requested address.
> 
> If requested_addr was NULL, no_align will be set to "false" (we don't 
> know what we get, so we must reserve additional space for alignment 
> purposes).
> 
> However, it will be set to "true" if page size is equal to system size 
> (the OS will return pointer that is already aligned to system page size, 
> so we don't need to align the result and thus don't need to reserve 
> additional space for alignment).
> 
> If requested address wasn't null, again we don't need alignment if 
> system page size is equal to requested page size, as any resulting 
> address will be already page-aligned (hence no_align set to "true").
> 
> If requested address wasn't already page-aligned and page size is not 
> equal to system page size, then we set "no_align" to false, because we 
> will need to align the resulting address.
> 
> The crucial part to understand is that the logic here is inverted - "if 
> requested address isn't NULL, and if the requested address is already 
> aligned (i.e. (addr & pgsz-1) == 0), then we *don't* need to align the 
> address". So, if the requested address is *not* aligned, "no_align" must 
> be set to false - because we *will* need to align the address.
> 
> As an added bonus, we have regression testing identifying this patch as 
> cause for numerous regressions :)

On reflection, I think i understand what you're getting at now, and that 
a different fix is required :)

The issue at hand isn't whether the requested address is or isn't 
aligned - it's that we need to make sure we always get aligned address 
as a result. You have highlighted a case where we might ask for a 
page-aligned address, but end up getting a different one, but since 
we've set no_align to "true", we won't align the resulting "wrong" address.

So it seems to me that the issue is, is there a possibility that we get 
an unaligned address? The answer lies in a different flag - 
addr_is_hint. That will tell us if we will discard the resulting address 
if we don't get what we want.

So really, the only cases we should *not* align the resulting address are:

1) if page size is equal to that of system page size, or
2) if requested addr isn't NULL, *and* it's page aligned, *and* 
addr_is_hint is not true (i.e. we will discard the address if it's not 
the one we will get)

In the second case, that "addr_is_hint" is our guarantee that we don't 
need to align address. So, resulting code should rather look like:

	no_align = (requested_addr != NULL &&
		((uintptr_t)requested_addr & (page_sz - 1)) &&
		!addr_is_hint) ||
		page_sz == system_page_sz;

Makes sense?

-- 
Thanks,
Anatoly


More information about the dev mailing list