All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2] vector: return false if realloc fails in vector_alloc_slot func
@ 2020-08-11  3:23 Zhiqiang Liu
  2020-08-11  9:46 ` Martin Wilck
  0 siblings, 1 reply; 3+ messages in thread
From: Zhiqiang Liu @ 2020-08-11  3:23 UTC (permalink / raw)
  To: Benjamin Marzinski, Martin Wilck, christophe.varoqui, kabelac
  Cc: linfeilong, Yanxiaodan, dm-devel, lixiaokeng


In vector_alloc_slot func, if REALLOC fails, it means new slot
allocation fails. However, it just update v->allocated and then
return the old v->slot without new slot. So, the caller will take
the last old slot as the new allocated slot, and use it by calling
vector_set_slot func. Finally, the data of last slot is lost.

Here, we rewrite vector_alloc_slot as suggested by Martin Wilck:
 - increment v->allocated only after successful allocation,
 - avoid the "if (v->slot)" conditional by just calling realloc(),
 - make sure all newly allocated vector elements are set to NULL,
 - change return value to bool.

Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
Signed-off-by: lixiaokeng <lixiaokeng@huawei.com>
---
 libmultipath/config.c       |  2 +-
 libmultipath/foreign.c      |  2 +-
 libmultipath/foreign/nvme.c |  6 +++---
 libmultipath/vector.c       | 22 +++++++++-------------
 libmultipath/vector.h       |  6 ++++--
 5 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/libmultipath/config.c b/libmultipath/config.c
index 49723add..4f5cefda 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -131,7 +131,7 @@ find_hwe (const struct _vector *hwtable,
 	vector_foreach_slot_backwards (hwtable, tmp, i) {
 		if (hwe_regmatch(tmp, vendor, product, revision))
 			continue;
-		if (vector_alloc_slot(result) != NULL) {
+		if (vector_alloc_slot(result)) {
 			vector_set_slot(result, tmp);
 			n++;
 		}
diff --git a/libmultipath/foreign.c b/libmultipath/foreign.c
index 26f92672..c2335ed5 100644
--- a/libmultipath/foreign.c
+++ b/libmultipath/foreign.c
@@ -236,7 +236,7 @@ static int _init_foreign(const char *multipath_dir, const char *const enable)
 			goto dl_err;
 		}

-		if (vector_alloc_slot(foreigns) == NULL) {
+		if (!vector_alloc_slot(foreigns)) {
 			goto dl_err;
 		}

diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
index da85e515..88b6aee2 100644
--- a/libmultipath/foreign/nvme.c
+++ b/libmultipath/foreign/nvme.c
@@ -731,12 +731,12 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
 		test_ana_support(map, path->ctl);

 		path->pg.gen.ops = &nvme_pg_ops;
-		if (vector_alloc_slot(&path->pg.pathvec) == NULL) {
+		if (!vector_alloc_slot(&path->pg.pathvec)) {
 			cleanup_nvme_path(path);
 			continue;
 		}
 		vector_set_slot(&path->pg.pathvec, path);
-		if (vector_alloc_slot(&map->pgvec) == NULL) {
+		if (!vector_alloc_slot(&map->pgvec)) {
 			cleanup_nvme_path(path);
 			continue;
 		}
@@ -792,7 +792,7 @@ static int _add_map(struct context *ctx, struct udev_device *ud,
 	map->subsys = subsys;
 	map->gen.ops = &nvme_map_ops;

-	if (vector_alloc_slot(ctx->mpvec) == NULL) {
+	if (!vector_alloc_slot(ctx->mpvec)) {
 		cleanup_nvme_map(map);
 		return FOREIGN_ERR;
 	}
diff --git a/libmultipath/vector.c b/libmultipath/vector.c
index 501cf4c5..39e2c20f 100644
--- a/libmultipath/vector.c
+++ b/libmultipath/vector.c
@@ -35,26 +35,22 @@ vector_alloc(void)
 }

 /* allocated one slot */
-void *
+bool
 vector_alloc_slot(vector v)
 {
 	void *new_slot = NULL;

 	if (!v)
-		return NULL;
-
-	v->allocated += VECTOR_DEFAULT_SIZE;
-	if (v->slot)
-		new_slot = REALLOC(v->slot, sizeof (void *) * v->allocated);
-	else
-		new_slot = (void *) MALLOC(sizeof (void *) * v->allocated);
+		return false;

+	new_slot = REALLOC(v->slot, sizeof (void *) * (v->allocated + VECTOR_DEFAULT_SIZE));
 	if (!new_slot)
-		v->allocated -= VECTOR_DEFAULT_SIZE;
-	else
-		v->slot = new_slot;
+		return false;

-	return v->slot;
+	v->slot = new_slot;
+	v->allocated += VECTOR_DEFAULT_SIZE;
+	v->slot[VECTOR_SIZE(v) - 1] = NULL;
+	return true;
 }

 int
@@ -203,7 +199,7 @@ int vector_find_or_add_slot(vector v, void *value)

 	if (n >= 0)
 		return n;
-	if (vector_alloc_slot(v) == NULL)
+	if (!vector_alloc_slot(v))
 		return -1;
 	vector_set_slot(v, value);
 	return VECTOR_SIZE(v) - 1;
diff --git a/libmultipath/vector.h b/libmultipath/vector.h
index e16ec461..cb64b7d6 100644
--- a/libmultipath/vector.h
+++ b/libmultipath/vector.h
@@ -23,6 +23,8 @@
 #ifndef _VECTOR_H
 #define _VECTOR_H

+#include <stdbool.h>
+
 /* vector definition */
 struct _vector {
 	int allocated;
@@ -60,7 +62,7 @@ typedef struct _vector *vector;
 			__t = vector_alloc();				\
 		if (__t != NULL) {					\
 			vector_foreach_slot(__v, __j, __i) {		\
-				if (vector_alloc_slot(__t) == NULL) {	\
+				if (!vector_alloc_slot(__t)) {	\
 					vector_free(__t);		\
 					__t = NULL;			\
 					break;				\
@@ -73,7 +75,7 @@ typedef struct _vector *vector;

 /* Prototypes */
 extern vector vector_alloc(void);
-extern void *vector_alloc_slot(vector v);
+extern bool vector_alloc_slot(vector v);
 vector vector_reset(vector v);
 extern void vector_free(vector v);
 #define vector_free_const(x) vector_free((vector)(long)(x))
-- 
2.24.0.windows.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH V2] vector: return false if realloc fails in vector_alloc_slot func
  2020-08-11  3:23 [PATCH V2] vector: return false if realloc fails in vector_alloc_slot func Zhiqiang Liu
@ 2020-08-11  9:46 ` Martin Wilck
  2020-08-12  7:25   ` Zhiqiang Liu
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Wilck @ 2020-08-11  9:46 UTC (permalink / raw)
  To: Zhiqiang Liu, Benjamin Marzinski, christophe.varoqui, kabelac
  Cc: linfeilong, Yanxiaodan, dm-devel, lixiaokeng

On Tue, 2020-08-11 at 11:23 +0800, Zhiqiang Liu wrote:
> In vector_alloc_slot func, if REALLOC fails, it means new slot
> allocation fails. However, it just update v->allocated and then
> return the old v->slot without new slot. So, the caller will take
> the last old slot as the new allocated slot, and use it by calling
> vector_set_slot func. Finally, the data of last slot is lost.
> 
> Here, we rewrite vector_alloc_slot as suggested by Martin Wilck:
>  - increment v->allocated only after successful allocation,
>  - avoid the "if (v->slot)" conditional by just calling realloc(),
>  - make sure all newly allocated vector elements are set to NULL,
>  - change return value to bool.
> 
> Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
> Signed-off-by: lixiaokeng <lixiaokeng@huawei.com>

Thanks a lot, this is very nice. We're almost there (see below).

> diff --git a/libmultipath/vector.c b/libmultipath/vector.c
> index 501cf4c5..39e2c20f 100644
> --- a/libmultipath/vector.c
> +++ b/libmultipath/vector.c
> @@ -35,26 +35,22 @@ vector_alloc(void)
>  }
> 
>  /* allocated one slot */
> -void *
> +bool
>  vector_alloc_slot(vector v)
>  {
>  	void *new_slot = NULL;
> 
>  	if (!v)
> -		return NULL;
> -
> -	v->allocated += VECTOR_DEFAULT_SIZE;
> -	if (v->slot)
> -		new_slot = REALLOC(v->slot, sizeof (void *) * v-
> >allocated);
> -	else
> -		new_slot = (void *) MALLOC(sizeof (void *) * v-
> >allocated);
> +		return false;
> 
> +	new_slot = REALLOC(v->slot, sizeof (void *) * (v->allocated +
> VECTOR_DEFAULT_SIZE));

Please wrap this line. We basically still use a 80-columns limit, with
the exception of string constants (mostly condlog() lines). We don't
strictly enforce it, but 92 columns is a bit too much for my taste.

>  	if (!new_slot)
> -		v->allocated -= VECTOR_DEFAULT_SIZE;
> -	else
> -		v->slot = new_slot;
> +		return false;
> 
> -	return v->slot;
> +	v->slot = new_slot;
> +	v->allocated += VECTOR_DEFAULT_SIZE;
> +	v->slot[VECTOR_SIZE(v) - 1] = NULL;

This assumes that VECTOR_DEFAULT_SIZE == 1. While that has been true
essentially forever, there's no guarantee for the future. Better use a
for loop, or memset().

Regards
Martin

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH V2] vector: return false if realloc fails in vector_alloc_slot func
  2020-08-11  9:46 ` Martin Wilck
@ 2020-08-12  7:25   ` Zhiqiang Liu
  0 siblings, 0 replies; 3+ messages in thread
From: Zhiqiang Liu @ 2020-08-12  7:25 UTC (permalink / raw)
  To: Martin Wilck, Benjamin Marzinski, christophe.varoqui, kabelac
  Cc: linfeilong, Yanxiaodan, dm-devel, lixiaokeng



On 2020/8/11 17:46, Martin Wilck wrote:
> On Tue, 2020-08-11 at 11:23 +0800, Zhiqiang Liu wrote:
> 
>> diff --git a/libmultipath/vector.c b/libmultipath/vector.c
>> index 501cf4c5..39e2c20f 100644
>> --- a/libmultipath/vector.c
>> +++ b/libmultipath/vector.c
>> @@ -35,26 +35,22 @@ vector_alloc(void)
>>  }
>>
>>  /* allocated one slot */
>> -void *
>> +bool
>>  vector_alloc_slot(vector v)
>>  {
>>  	void *new_slot = NULL;
>>
>>  	if (!v)
>> -		return NULL;
>> -
>> -	v->allocated += VECTOR_DEFAULT_SIZE;
>> -	if (v->slot)
>> -		new_slot = REALLOC(v->slot, sizeof (void *) * v-
>>> allocated);
>> -	else
>> -		new_slot = (void *) MALLOC(sizeof (void *) * v-
>>> allocated);
>> +		return false;
>>
>> +	new_slot = REALLOC(v->slot, sizeof (void *) * (v->allocated +
>> VECTOR_DEFAULT_SIZE));
> 
> Please wrap this line. We basically still use a 80-columns limit, with
> the exception of string constants (mostly condlog() lines). We don't
> strictly enforce it, but 92 columns is a bit too much for my taste.
Thanks for your reply.
I will introduce new var to shorten this line and init new slot with
using loop in the v3 patch.

Thanks again.

Regards.
Zhiqiang Liu

> 
>>  	if (!new_slot)
>> -		v->allocated -= VECTOR_DEFAULT_SIZE;
>> -	else
>> -		v->slot = new_slot;
>> +		return false;
>>
>> -	return v->slot;
>> +	v->slot = new_slot;
>> +	v->allocated += VECTOR_DEFAULT_SIZE;
>> +	v->slot[VECTOR_SIZE(v) - 1] = NULL;
> 
> This assumes that VECTOR_DEFAULT_SIZE == 1. While that has been true
> essentially forever, there's no guarantee for the future. Better use a
> for loop, or memset().
> 
> Regards
> Martin
> 
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-08-12  7:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-11  3:23 [PATCH V2] vector: return false if realloc fails in vector_alloc_slot func Zhiqiang Liu
2020-08-11  9:46 ` Martin Wilck
2020-08-12  7:25   ` Zhiqiang Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.