Refactor spa_load_l2cache to make build happy

In case sav->sav_config was NULL the body of the function
would skip the iteration of the l2 cache devices and will
just cleanup the old devices. However, this wasn't very obvious
since the null check was performed after the loop body and after
the old devices were cleaned. Refactor the code so that it's now
obvious when the iteration of the l2cache devices is skipped.

This fixes the following cppcheck warning:

[module/zfs/spa.c:1552]: (error) Possible null pointer dereference: newvdevs

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Nikolay Borisov <n.borisov.lkml@gmail.com>
Closes #5087
This commit is contained in:
Nikolay Borisov 2016-09-10 23:06:17 +03:00 committed by Brian Behlendorf
parent 20aa7a4e31
commit 67d6082494

View File

@ -1528,20 +1528,21 @@ spa_load_l2cache(spa_t *spa)
ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
if (sav->sav_config != NULL) {
VERIFY(nvlist_lookup_nvlist_array(sav->sav_config,
ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0);
newvdevs = kmem_alloc(nl2cache * sizeof (void *), KM_SLEEP);
} else {
nl2cache = 0;
newvdevs = NULL;
}
oldvdevs = sav->sav_vdevs; oldvdevs = sav->sav_vdevs;
oldnvdevs = sav->sav_count; oldnvdevs = sav->sav_count;
sav->sav_vdevs = NULL; sav->sav_vdevs = NULL;
sav->sav_count = 0; sav->sav_count = 0;
if (sav->sav_config == NULL) {
nl2cache = 0;
newvdevs = NULL;
goto out;
}
VERIFY(nvlist_lookup_nvlist_array(sav->sav_config,
ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0);
newvdevs = kmem_alloc(nl2cache * sizeof (void *), KM_SLEEP);
/* /*
* Process new nvlist of vdevs. * Process new nvlist of vdevs.
*/ */
@ -1592,6 +1593,24 @@ spa_load_l2cache(spa_t *spa)
} }
} }
sav->sav_vdevs = newvdevs;
sav->sav_count = (int)nl2cache;
/*
* Recompute the stashed list of l2cache devices, with status
* information this time.
*/
VERIFY(nvlist_remove(sav->sav_config, ZPOOL_CONFIG_L2CACHE,
DATA_TYPE_NVLIST_ARRAY) == 0);
l2cache = kmem_alloc(sav->sav_count * sizeof (void *), KM_SLEEP);
for (i = 0; i < sav->sav_count; i++)
l2cache[i] = vdev_config_generate(spa,
sav->sav_vdevs[i], B_TRUE, VDEV_CONFIG_L2CACHE);
VERIFY(nvlist_add_nvlist_array(sav->sav_config,
ZPOOL_CONFIG_L2CACHE, l2cache, sav->sav_count) == 0);
out:
/* /*
* Purge vdevs that were dropped * Purge vdevs that were dropped
*/ */
@ -1613,26 +1632,6 @@ spa_load_l2cache(spa_t *spa)
if (oldvdevs) if (oldvdevs)
kmem_free(oldvdevs, oldnvdevs * sizeof (void *)); kmem_free(oldvdevs, oldnvdevs * sizeof (void *));
if (sav->sav_config == NULL)
goto out;
sav->sav_vdevs = newvdevs;
sav->sav_count = (int)nl2cache;
/*
* Recompute the stashed list of l2cache devices, with status
* information this time.
*/
VERIFY(nvlist_remove(sav->sav_config, ZPOOL_CONFIG_L2CACHE,
DATA_TYPE_NVLIST_ARRAY) == 0);
l2cache = kmem_alloc(sav->sav_count * sizeof (void *), KM_SLEEP);
for (i = 0; i < sav->sav_count; i++)
l2cache[i] = vdev_config_generate(spa,
sav->sav_vdevs[i], B_TRUE, VDEV_CONFIG_L2CACHE);
VERIFY(nvlist_add_nvlist_array(sav->sav_config,
ZPOOL_CONFIG_L2CACHE, l2cache, sav->sav_count) == 0);
out:
for (i = 0; i < sav->sav_count; i++) for (i = 0; i < sav->sav_count; i++)
nvlist_free(l2cache[i]); nvlist_free(l2cache[i]);
if (sav->sav_count) if (sav->sav_count)