[dpdk-dev,v2,1/2] test/mempool_perf: Free mempool on exit

Message ID 20170406064549.7966-1-santosh.shukla@caviumnetworks.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Santosh Shukla April 6, 2017, 6:45 a.m. UTC
  Mempool_perf test not freeing pool memory.

Cc: stable@dpdk.org
Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
Acked-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
v1 --> v2:
 * Fixed patch context

 test/test/test_mempool_perf.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)
  

Comments

Olivier Matz April 7, 2017, 3:51 p.m. UTC | #1
Hi Santosh,

On Thu,  6 Apr 2017 12:15:48 +0530, Santosh Shukla <santosh.shukla@caviumnetworks.com> wrote:
> Mempool_perf test not freeing pool memory.
> 
> Cc: stable@dpdk.org
> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
> Acked-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
> v1 --> v2:
>  * Fixed patch context
> 
>  test/test/test_mempool_perf.c | 31 +++++++++++++++++++------------
>  1 file changed, 19 insertions(+), 12 deletions(-)
> 
> diff --git a/test/test/test_mempool_perf.c b/test/test/test_mempool_perf.c
> index ebf1721ac..3c45971ab 100644
> --- a/test/test/test_mempool_perf.c
> +++ b/test/test/test_mempool_perf.c
> @@ -312,6 +312,8 @@ do_one_mempool_test(unsigned cores)
>  static int
>  test_mempool_perf(void)
>  {
> +	int ret = -1;
> +
>  	rte_atomic32_init(&synchro);
>  
>  	/* create a mempool (without cache) */
> @@ -322,7 +324,7 @@ test_mempool_perf(void)
>  						my_obj_init, NULL,
>  						SOCKET_ID_ANY, 0);
>  	if (mp_nocache == NULL)
> -		return -1;
> +		goto err;
>  
>  	/* create a mempool (with cache) */
>  	if (mp_cache == NULL)

[...]

>  
> -	return 0;
> +	ret = 0;
> +
> +err:
> +	rte_mempool_free(mp_cache);
> +	rte_mempool_free(mp_nocache);
> +	return ret;


Since mp_cache and mp_nocache are global variables, this won't
work properly due to the way mempool are created:

	/* create a mempool (without cache) */
	if (mp_nocache == NULL)
	        mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE,
	                                        MEMPOOL_ELT_SIZE, 0, 0,
	                                        NULL, NULL,
	                                        my_obj_init, NULL,
	                                        SOCKET_ID_ANY, 0);

The if() should be removed, else we'll have a use after free the next
time.

If you want to do more clean-up, you can try to remove the global variables,
but it's maybe harder.

Thanks,
Olivier
  
Santosh Shukla April 9, 2017, 7:43 p.m. UTC | #2
Hi Olivier,

On Monday 10 April 2017 12:47 AM, Shukla, Santosh wrote:

>
>
> --------------------------------------------------------------------------------
> *From:* Olivier Matz <olivier.matz@6wind.com>
> *Sent:* Friday, April 7, 2017 9:21 PM
> *To:* Shukla, Santosh
> *Cc:* dev@dpdk.org; hemant.agrawal@nxp.com; shreyansh.jain@nxp.com; stable@dpdk.org
> *Subject:* Re: [PATCH v2 1/2] test/mempool_perf: Free mempool on exit
> Hi Santosh,
>
> On Thu,  6 Apr 2017 12:15:48 +0530, Santosh Shukla 
> <santosh.shukla@caviumnetworks.com> wrote:
> > Mempool_perf test not freeing pool memory.
> >
> > Cc: stable@dpdk.org
> > Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
> > Acked-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> > ---
> > v1 --> v2:
> >  * Fixed patch context
> >
> >  test/test/test_mempool_perf.c | 31 +++++++++++++++++++------------
> >  1 file changed, 19 insertions(+), 12 deletions(-)
> >
> > diff --git a/test/test/test_mempool_perf.c b/test/test/test_mempool_perf.c
> > index ebf1721ac..3c45971ab 100644
> > --- a/test/test/test_mempool_perf.c
> > +++ b/test/test/test_mempool_perf.c
> > @@ -312,6 +312,8 @@ do_one_mempool_test(unsigned cores)
> >  static int
> >  test_mempool_perf(void)
> >  {
> > +     int ret = -1;
> > +
> >        rte_atomic32_init(&synchro);
> >
> >        /* create a mempool (without cache) */
> > @@ -322,7 +324,7 @@ test_mempool_perf(void)
> >                                                my_obj_init, NULL,
> >                                                SOCKET_ID_ANY, 0);
> >        if (mp_nocache == NULL)
> > -             return -1;
> > +             goto err;
> >
> >        /* create a mempool (with cache) */
> >        if (mp_cache == NULL)
>
> [...]
>
> >
> > -     return 0;
> > +     ret = 0;
> > +
> > +err:
> > +     rte_mempool_free(mp_cache);
> > +     rte_mempool_free(mp_nocache);
> > +     return ret;
>
>
> Since mp_cache and mp_nocache are global variables, this won't
> work properly due to the way mempool are created:
>
>          /* create a mempool (without cache) */
>          if (mp_nocache == NULL)
>                  mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE,
>                                                  MEMPOOL_ELT_SIZE, 0, 0,
>                                                  NULL, NULL,
>                                                  my_obj_init, NULL,
>                                                  SOCKET_ID_ANY, 0);
>
> The if() should be removed, else we'll have a use after free the next
> time.

I understand your point.
But I think problem is rte_mempool_free() not referencing mp = null
after freeing resources. Result of that is mp_nocache still has valid 
address, Although internal resources (mz/_ops_handle) were actually freed by
rte_mempool_free(), right?

So rather removing above if(), why not
- Application explicit set mp_nocache = NULL after mempool_free().
ie.. 

err:
	rte_mempool_free(xxx);
	xxx = NULL;


Or
- Let rte_mempool_free() { - do mp = null; }

And yes remove that if condition anyway. As its a dead-code
 for either of above 2 options.

Does that make sense to you? If so then which one you prefer?

> If you want to do more clean-up, you can try to remove the global variables,
> but it's maybe harder.

Removing global var won't be harder imo, May be you know more but
here is my point of view, after going through code:

- All test_func like
do_one_mempool_test -> launch_cores --> per_lcore_mempool_test -> using 'mp'

where 'mp' is global. 

how about,
- As you said Yes - remove global var ie.. mp_cache/nocache, default_pool, mp
- Add 'rte_mempool *mp' as argument in do_one_mempool_test() func and other func too.

Thus get rid of globals from app.

Does that make sense to you? 

Thanks,.
Santosh

> Thanks,
> Olivier
  
Olivier Matz April 10, 2017, 8:09 p.m. UTC | #3
Hi Santosh,

On Mon, 10 Apr 2017 01:13:43 +0530
santosh <santosh.shukla@caviumnetworks.com> wrote:

> Hi Olivier,
> 
> On Monday 10 April 2017 12:47 AM, Shukla, Santosh wrote:
> 
> >
> >
> > --------------------------------------------------------------------------------
> > *From:* Olivier Matz <olivier.matz@6wind.com>
> > *Sent:* Friday, April 7, 2017 9:21 PM
> > *To:* Shukla, Santosh
> > *Cc:* dev@dpdk.org; hemant.agrawal@nxp.com; shreyansh.jain@nxp.com; stable@dpdk.org
> > *Subject:* Re: [PATCH v2 1/2] test/mempool_perf: Free mempool on exit
> > Hi Santosh,
> >
> > On Thu,  6 Apr 2017 12:15:48 +0530, Santosh Shukla 
> > <santosh.shukla@caviumnetworks.com> wrote:  
> > > Mempool_perf test not freeing pool memory.
> > >
> > > Cc: stable@dpdk.org
> > > Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
> > > Acked-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> > > ---
> > > v1 --> v2:
> > >  * Fixed patch context
> > >
> > >  test/test/test_mempool_perf.c | 31 +++++++++++++++++++------------
> > >  1 file changed, 19 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/test/test/test_mempool_perf.c b/test/test/test_mempool_perf.c
> > > index ebf1721ac..3c45971ab 100644
> > > --- a/test/test/test_mempool_perf.c
> > > +++ b/test/test/test_mempool_perf.c
> > > @@ -312,6 +312,8 @@ do_one_mempool_test(unsigned cores)
> > >  static int
> > >  test_mempool_perf(void)
> > >  {
> > > +     int ret = -1;
> > > +
> > >        rte_atomic32_init(&synchro);
> > >
> > >        /* create a mempool (without cache) */
> > > @@ -322,7 +324,7 @@ test_mempool_perf(void)
> > >                                                my_obj_init, NULL,
> > >                                                SOCKET_ID_ANY, 0);
> > >        if (mp_nocache == NULL)
> > > -             return -1;
> > > +             goto err;
> > >
> > >        /* create a mempool (with cache) */
> > >        if (mp_cache == NULL)  
> >
> > [...]
> >  
> > >
> > > -     return 0;
> > > +     ret = 0;
> > > +
> > > +err:
> > > +     rte_mempool_free(mp_cache);
> > > +     rte_mempool_free(mp_nocache);
> > > +     return ret;  
> >
> >
> > Since mp_cache and mp_nocache are global variables, this won't
> > work properly due to the way mempool are created:
> >
> >          /* create a mempool (without cache) */
> >          if (mp_nocache == NULL)
> >                  mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE,
> >                                                  MEMPOOL_ELT_SIZE, 0, 0,
> >                                                  NULL, NULL,
> >                                                  my_obj_init, NULL,
> >                                                  SOCKET_ID_ANY, 0);
> >
> > The if() should be removed, else we'll have a use after free the next
> > time.  
> 
> I understand your point.
> But I think problem is rte_mempool_free() not referencing mp = null
> after freeing resources. Result of that is mp_nocache still has valid 
> address, Although internal resources (mz/_ops_handle) were actually freed by
> rte_mempool_free(), right?
> 
> So rather removing above if(), why not
> - Application explicit set mp_nocache = NULL after mempool_free().
> ie.. 
> 
> err:
> 	rte_mempool_free(xxx);
> 	xxx = NULL;
> 
> 
> Or
> - Let rte_mempool_free() { - do mp = null; }
> 
> And yes remove that if condition anyway. As its a dead-code
>  for either of above 2 options.
> 
> Does that make sense to you? If so then which one you prefer?

Yes, it makes sense.
My first preference would be removing the global vars (as suggested
below). Else your proposition is ok too.

> 
> > If you want to do more clean-up, you can try to remove the global variables,
> > but it's maybe harder.  
> 
> Removing global var won't be harder imo, May be you know more but
> here is my point of view, after going through code:
> 
> - All test_func like
> do_one_mempool_test -> launch_cores --> per_lcore_mempool_test -> using 'mp'
> 
> where 'mp' is global. 
> 
> how about,
> - As you said Yes - remove global var ie.. mp_cache/nocache, default_pool, mp
> - Add 'rte_mempool *mp' as argument in do_one_mempool_test() func and other func too.
> 
> Thus get rid of globals from app.
> 
> Does that make sense to you? 

Yes, looks good. It would be clearer without global vars.

Historically, it was not possible to free a mempool, that's why it was
done like this.


Thanks!
Olivier
  

Patch

diff --git a/test/test/test_mempool_perf.c b/test/test/test_mempool_perf.c
index ebf1721ac..3c45971ab 100644
--- a/test/test/test_mempool_perf.c
+++ b/test/test/test_mempool_perf.c
@@ -312,6 +312,8 @@  do_one_mempool_test(unsigned cores)
 static int
 test_mempool_perf(void)
 {
+	int ret = -1;
+
 	rte_atomic32_init(&synchro);
 
 	/* create a mempool (without cache) */
@@ -322,7 +324,7 @@  test_mempool_perf(void)
 						my_obj_init, NULL,
 						SOCKET_ID_ANY, 0);
 	if (mp_nocache == NULL)
-		return -1;
+		goto err;
 
 	/* create a mempool (with cache) */
 	if (mp_cache == NULL)
@@ -333,33 +335,33 @@  test_mempool_perf(void)
 					      my_obj_init, NULL,
 					      SOCKET_ID_ANY, 0);
 	if (mp_cache == NULL)
-		return -1;
+		goto err;
 
 	/* performance test with 1, 2 and max cores */
 	printf("start performance test (without cache)\n");
 	mp = mp_nocache;
 
 	if (do_one_mempool_test(1) < 0)
-		return -1;
+		goto err;
 
 	if (do_one_mempool_test(2) < 0)
-		return -1;
+		goto err;
 
 	if (do_one_mempool_test(rte_lcore_count()) < 0)
-		return -1;
+		goto err;
 
 	/* performance test with 1, 2 and max cores */
 	printf("start performance test (with cache)\n");
 	mp = mp_cache;
 
 	if (do_one_mempool_test(1) < 0)
-		return -1;
+		goto err;
 
 	if (do_one_mempool_test(2) < 0)
-		return -1;
+		goto err;
 
 	if (do_one_mempool_test(rte_lcore_count()) < 0)
-		return -1;
+		goto err;
 
 	/* performance test with 1, 2 and max cores */
 	printf("start performance test (with user-owned cache)\n");
@@ -367,17 +369,22 @@  test_mempool_perf(void)
 	use_external_cache = 1;
 
 	if (do_one_mempool_test(1) < 0)
-		return -1;
+		goto err;
 
 	if (do_one_mempool_test(2) < 0)
-		return -1;
+		goto err;
 
 	if (do_one_mempool_test(rte_lcore_count()) < 0)
-		return -1;
+		goto err;
 
 	rte_mempool_list_dump(stdout);
 
-	return 0;
+	ret = 0;
+
+err:
+	rte_mempool_free(mp_cache);
+	rte_mempool_free(mp_nocache);
+	return ret;
 }
 
 REGISTER_TEST_COMMAND(mempool_perf_autotest, test_mempool_perf);