diff mbox series

[V2,3/6,RFC] xen/common: Introduce _xrealloc function

Message ID 1564763985-20312-4-git-send-email-olekstysh@gmail.com (mailing list archive)
State Superseded
Headers show
Series iommu/arm: Add Renesas IPMMU-VMSA support + Linux's iommu_fwspec | expand

Commit Message

Oleksandr Tyshchenko Aug. 2, 2019, 4:39 p.m. UTC
From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

Next patch in this series will make use of it.

Original patch was initially posted by Sameer Goel:
https://lists.xen.org/archives/html/xen-devel/2017-06/msg00858.html

This could be considered as another attempt to add it:
https://www.mail-archive.com/kexec@lists.infradead.org/msg21335.html

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
CC: George Dunlap <George.Dunlap@eu.citrix.com>
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Jan Beulich <jbeulich@suse.com>
CC: Julien Grall <julien.grall@arm.com>
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Tim Deegan <tim@xen.org>
CC: Wei Liu <wl@xen.org>

---
   [As it was previously discussed with Julien in IRC]

   The reason for this patch to be an RFC is that patch itself is not
   completely correct and I don't fully understand what/how should
   be done for this patch to be accepted. Or whether community even
   wants this to go in. So, to avoid bike shedding, the first target is
   to collect feedback from the maintainers.

   In a nutshell, the upcoming "iommu_fwspec" support on ARM
   is going to use xrealloc when adding new device ID.
   
   We really want to have "iommu_fwspec" support which will give us
   a generic abstract way to add new device to the IOMMU based on
   the generic IOMMU DT binding.
   
   This is how Linux does:
   https://github.com/torvalds/linux/blob/master/drivers/iommu/iommu.c#L2257
   and we are doing the similar in next patch of this thread:
   "iommu/arm: Add lightweight iommu_fwspec support"
---
 xen/common/xmalloc_tlsf.c | 21 +++++++++++++++++++++
 xen/include/xen/xmalloc.h |  1 +
 2 files changed, 22 insertions(+)

Comments

Jan Beulich Aug. 5, 2019, 10:02 a.m. UTC | #1
On 02.08.2019 18:39, Oleksandr Tyshchenko wrote:
> --- a/xen/common/xmalloc_tlsf.c
> +++ b/xen/common/xmalloc_tlsf.c
> @@ -610,6 +610,27 @@ void *_xzalloc(unsigned long size, unsigned long align)
>       return p ? memset(p, 0, size) : p;
>   }
>   
> +void *_xrealloc(void *p, unsigned long new_size, unsigned long align)
> +{
> +    void *new_p;
> +
> +    if ( !new_size )
> +    {
> +        xfree(p);
> +        return NULL;
> +    }
> +
> +    new_p = _xmalloc(new_size, align);
> +
> +    if ( new_p && p )
> +    {
> +        memcpy(new_p, p, new_size);
> +        xfree(p);
> +    }
> +
> +    return new_p;
> +}

While I can see why having a re-allocation function may be handy,
explicit / direct use of _xmalloc() and _xzalloc() are discouraged,
in favor of the more type-safe underscore-less variants. I can't
see though how a type-safe "realloc" could look like, except for
arrays. If resizing arrays is all you're after, I'd like to
recommend to go that route rather then the suggested one here. If
resizing arbitrary objects is the goal, then what you suggest may
be the only route, but I'd still be not overly happy to see such
added.

Furthermore you don't even use internals of the allocator: It is
common practice to avoid re-allocation if the requested size fits
within the already allocated block. That's not the least helpful
because in such a case you can't possibly suffer any -ENOMEM
condition.

And finally - please note _xmalloc()'s and _xfree()'s use /
special casing of ZERO_BLOCK_PTR: You absolutely would need to
mirror this here.

Jan
Oleksandr Tyshchenko Aug. 6, 2019, 6:50 p.m. UTC | #2
On 05.08.19 13:02, Jan Beulich wrote:

Hi, Jan

> While I can see why having a re-allocation function may be handy,
> explicit / direct use of _xmalloc() and _xzalloc() are discouraged,
> in favor of the more type-safe underscore-less variants.

took into account


> I can't
> see though how a type-safe "realloc" could look like, except for
> arrays. If resizing arrays is all you're after, I'd like to
> recommend to go that route rather then the suggested one here. If
> resizing arbitrary objects is the goal, then what you suggest may
> be the only route, but I'd still be not overly happy to see such
> added.

My main goal is to get "ported" from Linux "iommu_fwspec" support 
(xrealloc user) in [1].

I tried to retain code as much as possible while porting. So, this patch 
adds almost the same thing what the ported code expects.

But, I would be OK to consider modifying a code in a way to resize an 
array as well as any other variants if present.


>
> Furthermore you don't even use internals of the allocator: It is
> common practice to avoid re-allocation if the requested size fits
> within the already allocated block. That's not the least helpful
> because in such a case you can't possibly suffer any -ENOMEM
> condition.

agree, took into account as well.


>
> And finally - please note _xmalloc()'s and _xfree()'s use /
> special casing of ZERO_BLOCK_PTR: You absolutely would need to
> mirror this here.

got it, will use for zero-size allocation


[1] 
https://lists.xenproject.org/archives/html/xen-devel/2019-08/msg00257.html


Thank you.
Volodymyr Babchuk Aug. 6, 2019, 7:51 p.m. UTC | #3
Hi Jan,

Jan Beulich writes:

> On 02.08.2019 18:39, Oleksandr Tyshchenko wrote:
>> --- a/xen/common/xmalloc_tlsf.c
>> +++ b/xen/common/xmalloc_tlsf.c
>> @@ -610,6 +610,27 @@ void *_xzalloc(unsigned long size, unsigned long align)
>>       return p ? memset(p, 0, size) : p;
>>   }
>>   
>> +void *_xrealloc(void *p, unsigned long new_size, unsigned long align)
>> +{
>> +    void *new_p;
>> +
>> +    if ( !new_size )
>> +    {
>> +        xfree(p);
>> +        return NULL;
>> +    }
>> +
>> +    new_p = _xmalloc(new_size, align);
>> +
>> +    if ( new_p && p )
>> +    {
>> +        memcpy(new_p, p, new_size);
>> +        xfree(p);
>> +    }
>> +
>> +    return new_p;
>> +}
>
> While I can see why having a re-allocation function may be handy,
> explicit / direct use of _xmalloc() and _xzalloc() are discouraged,
> in favor of the more type-safe underscore-less variants. I can't
> see though how a type-safe "realloc" could look like, except for
> arrays. If resizing arrays is all you're after, I'd like to
> recommend to go that route rather then the suggested one here. If
> resizing arbitrary objects is the goal, then what you suggest may
> be the only route, but I'd still be not overly happy to see such
> added.

I can see 3 uses for realloc:

 a. re-allocate generic data buffer
 b. re-allocate array
 c. re-allocate struct with flexible buffer.

option c. is about structures like this:

struct arrlen
{
        size_t len;
        int data[1];
};

This is Oleksandr's case.

So for option a. we can use _xreallocate(ptr, size, align)
For option b. we can use xrealloc_array(_ptr, _type, _num)
And for option c. I propose to implement the following macro:

#define realloc_flex_struct(_ptr, _type, _field, _len)                        \
 ((_type *)_xrealloc(_ptr, offsetof(_type, _field[_len]) , __alignof__(_type)))

It can be used in the following way:

newptr = realloc_flex_struct(ptr, struct arrlen, newsize);

As you can see, this approach is type-safe and covers Oleksanrd's case.
Jan Beulich Aug. 7, 2019, 6:22 a.m. UTC | #4
On 06.08.2019 20:50, Oleksandr wrote:
> On 05.08.19 13:02, Jan Beulich wrote:
>> I can't
>> see though how a type-safe "realloc" could look like, except for
>> arrays. If resizing arrays is all you're after, I'd like to
>> recommend to go that route rather then the suggested one here. If
>> resizing arbitrary objects is the goal, then what you suggest may
>> be the only route, but I'd still be not overly happy to see such
>> added.
> 
> My main goal is to get "ported" from Linux "iommu_fwspec" support (xrealloc user) in [1].
> 
> I tried to retain code as much as possible while porting. So, this patch adds almost the same thing what the ported code expects.
> 
> But, I would be OK to consider modifying a code in a way to resize an array as well as any other variants if present.

I've looked at the use in patch 4, and it really isn't an array
allocation. Even a basic allocation would use _xmalloc() in this
case (you'll find examples in the tree if you want). Nevertheless
I'd appreciate if the type-unsafe _xrealloc() didn't remain the
only re-allocation construct, as to avoiding people using it just
because there's no better alternative.

Jan
Jan Beulich Aug. 7, 2019, 6:26 a.m. UTC | #5
On 06.08.2019 21:51, Volodymyr Babchuk wrote:
> 
> Hi Jan,
> 
> Jan Beulich writes:
> 
>> On 02.08.2019 18:39, Oleksandr Tyshchenko wrote:
>>> --- a/xen/common/xmalloc_tlsf.c
>>> +++ b/xen/common/xmalloc_tlsf.c
>>> @@ -610,6 +610,27 @@ void *_xzalloc(unsigned long size, unsigned long align)
>>>        return p ? memset(p, 0, size) : p;
>>>    }
>>>    
>>> +void *_xrealloc(void *p, unsigned long new_size, unsigned long align)
>>> +{
>>> +    void *new_p;
>>> +
>>> +    if ( !new_size )
>>> +    {
>>> +        xfree(p);
>>> +        return NULL;
>>> +    }
>>> +
>>> +    new_p = _xmalloc(new_size, align);
>>> +
>>> +    if ( new_p && p )
>>> +    {
>>> +        memcpy(new_p, p, new_size);
>>> +        xfree(p);
>>> +    }
>>> +
>>> +    return new_p;
>>> +}
>>
>> While I can see why having a re-allocation function may be handy,
>> explicit / direct use of _xmalloc() and _xzalloc() are discouraged,
>> in favor of the more type-safe underscore-less variants. I can't
>> see though how a type-safe "realloc" could look like, except for
>> arrays. If resizing arrays is all you're after, I'd like to
>> recommend to go that route rather then the suggested one here. If
>> resizing arbitrary objects is the goal, then what you suggest may
>> be the only route, but I'd still be not overly happy to see such
>> added.
> 
> I can see 3 uses for realloc:
> 
>   a. re-allocate generic data buffer
>   b. re-allocate array
>   c. re-allocate struct with flexible buffer.
> 
> option c. is about structures like this:
> 
> struct arrlen
> {
>          size_t len;
>          int data[1];
> };
> 
> This is Oleksandr's case.
> 
> So for option a. we can use _xreallocate(ptr, size, align)
> For option b. we can use xrealloc_array(_ptr, _type, _num)
> And for option c. I propose to implement the following macro:
> 
> #define realloc_flex_struct(_ptr, _type, _field, _len)                        \
>   ((_type *)_xrealloc(_ptr, offsetof(_type, _field[_len]) , __alignof__(_type)))
> 
> It can be used in the following way:
> 
> newptr = realloc_flex_struct(ptr, struct arrlen, newsize);
> 
> As you can see, this approach is type-safe and covers Oleksanrd's case.

This looks fine to me, but then wants to be accompanied by a
similar xmalloc_flex_struct(), which could be used right away
to replace a number of open-coded instances of the above.

There's one more thing for the re-alloc case though (besides
cosmetic aspects): The incoming pointer should also be verified
to be of correct type.

Jan
Oleksandr Tyshchenko Aug. 7, 2019, 5:31 p.m. UTC | #6
Hi,


> Nevertheless
> I'd appreciate if the type-unsafe _xrealloc() didn't remain the
> only re-allocation construct, as to avoiding people using it just
> because there's no better alternative.

I got your point.
Oleksandr Tyshchenko Aug. 7, 2019, 6:36 p.m. UTC | #7
Hi, Jan, Volodymyr.


>>   c. re-allocate struct with flexible buffer.
>>
>> option c. is about structures like this:
>>
>> struct arrlen
>> {
>>          size_t len;
>>          int data[1];
>> };
>>
>> This is Oleksandr's case.
>>
>> So for option a. we can use _xreallocate(ptr, size, align)
>> For option b. we can use xrealloc_array(_ptr, _type, _num)
>> And for option c. I propose to implement the following macro:
>>
>> #define realloc_flex_struct(_ptr, _type, _field, 
>> _len)                        \
>>   ((_type *)_xrealloc(_ptr, offsetof(_type, _field[_len]) , 
>> __alignof__(_type)))
>>
>> It can be used in the following way:
>>
>> newptr = realloc_flex_struct(ptr, struct arrlen, newsize);
>>
>> As you can see, this approach is type-safe and covers Oleksanrd's case.
>
> This looks fine to me, but then wants to be accompanied by a
> similar xmalloc_flex_struct(), which could be used right away
> to replace a number of open-coded instances of the above.

Thank you Volodymyr for the idea. Looks like we can get a type-safe 
approach which looks suitable for my particular case.

So, I need to focus on the proper implementation of non type-safe 
(_xrealloc) variant in the first place taking into the account Jan's 
comments. Then I will be back to the suggested type-safe marco 
(realloc_flex_struct).


>
> There's one more thing for the re-alloc case though (besides
> cosmetic aspects): The incoming pointer should also be verified
> to be of correct type.

Jan, how this could be technically implemented, or are these any 
existing examples in Xen?


>
> Jan
Jan Beulich Aug. 8, 2019, 6:08 a.m. UTC | #8
On 07.08.2019 20:36, Oleksandr wrote:
>> There's one more thing for the re-alloc case though (besides
>> cosmetic aspects): The incoming pointer should also be verified
>> to be of correct type.
> 
> Jan, how this could be technically implemented, or are these any existing examples in Xen?

See x86's copy_to_guest_offset(), for example. To get the compiler
to emit a warning (at least), a (typically otherwise dead)
comparison of pointers is commonly used.

Jan
Jan Beulich Aug. 8, 2019, 7:05 a.m. UTC | #9
(I'm sorry if you receive duplicates of this, but I've got a reply
back from our mail system that several of the recipients did not
have their host names resolved correctly on the first attempt.)

On 07.08.2019 20:36, Oleksandr wrote:
>> There's one more thing for the re-alloc case though (besides
>> cosmetic aspects): The incoming pointer should also be verified
>> to be of correct type.
> 
> Jan, how this could be technically implemented, or are these any existing examples in Xen?

See x86's copy_to_guest_offset(), for example. To get the compiler
to emit a warning (at least), a (typically otherwise dead)
comparison of pointers is commonly used.

Jan
Oleksandr Tyshchenko Aug. 8, 2019, 11:05 a.m. UTC | #10
On 08.08.19 10:05, Jan Beulich wrote:

Hi Jan

> (I'm sorry if you receive duplicates of this, but I've got a reply
> back from our mail system that several of the recipients did not
> have their host names resolved correctly on the first attempt.)

Absolutely no problem.


>> Jan, how this could be technically implemented, or are these any existing examples in Xen?
> See x86's copy_to_guest_offset(), for example. To get the compiler
> to emit a warning (at least), a (typically otherwise dead)
> comparison of pointers is commonly used.


Thank you for the pointer. It is clear now.
diff mbox series

Patch

diff --git a/xen/common/xmalloc_tlsf.c b/xen/common/xmalloc_tlsf.c
index 2076953..c080763 100644
--- a/xen/common/xmalloc_tlsf.c
+++ b/xen/common/xmalloc_tlsf.c
@@ -610,6 +610,27 @@  void *_xzalloc(unsigned long size, unsigned long align)
     return p ? memset(p, 0, size) : p;
 }
 
+void *_xrealloc(void *p, unsigned long new_size, unsigned long align)
+{
+    void *new_p;
+
+    if ( !new_size )
+    {
+        xfree(p);
+        return NULL;
+    }
+
+    new_p = _xmalloc(new_size, align);
+
+    if ( new_p && p )
+    {
+        memcpy(new_p, p, new_size);
+        xfree(p);
+    }
+
+    return new_p;
+}
+
 void xfree(void *p)
 {
     struct bhdr *b;
diff --git a/xen/include/xen/xmalloc.h b/xen/include/xen/xmalloc.h
index b486fe4..63961ef 100644
--- a/xen/include/xen/xmalloc.h
+++ b/xen/include/xen/xmalloc.h
@@ -51,6 +51,7 @@  extern void xfree(void *);
 /* Underlying functions */
 extern void *_xmalloc(unsigned long size, unsigned long align);
 extern void *_xzalloc(unsigned long size, unsigned long align);
+extern void *_xrealloc(void *p, unsigned long new_size, unsigned long align);
 
 static inline void *_xmalloc_array(
     unsigned long size, unsigned long align, unsigned long num)