Cleanup: spa vdev processing should check NULL pointers
The PVS Studio 2016 FreeBSD kernel report stated: \contrib\opensolaris\uts\common\fs\zfs\spa.c (1341): error V595: The 'spa->spa_spares.sav_vdevs' pointer was utilized before it was verified against nullptr. Check lines: 1341, 1342. \sys\cddl\contrib\opensolaris\uts\common\fs\zfs\spa.c (1355): error V595: The 'spa->spa_l2cache.sav_vdevs' pointer was utilized before it was verified against nullptr. Check lines: 1355, 1357. \sys\cddl\contrib\opensolaris\uts\common\fs\zfs\spa.c (1398): error V595: The 'spa->spa_spares.sav_vdevs' pointer was utilized before it was verified against nullptr. Check lines: 1398, 1408. \sys\cddl\contrib\opensolaris\uts\common\fs\zfs\spa.c (1583): error V595: The 'oldvdevs' pointer was utilized before it was verified against nullptr. Check lines: 1583, 1595. In practice, all of these uses were safe because a NULL pointer implied a 0 vdev count, which kept us from iterating over vdevs. However, rearranging the code to check the pointer first is not a terrible micro-optimization and makes it more readable, so let us do that. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Brian Atkinson <batkinson@lanl.gov> Signed-off-by: Richard Yao <richard.yao@alumni.stonybrook.edu> Closes #14456
This commit is contained in:
parent
3a7d2a0ce0
commit
cfb49616cd
|
@ -1714,9 +1714,9 @@ spa_unload(spa_t *spa)
|
||||||
*/
|
*/
|
||||||
spa_l2cache_drop(spa);
|
spa_l2cache_drop(spa);
|
||||||
|
|
||||||
for (int i = 0; i < spa->spa_spares.sav_count; i++)
|
|
||||||
vdev_free(spa->spa_spares.sav_vdevs[i]);
|
|
||||||
if (spa->spa_spares.sav_vdevs) {
|
if (spa->spa_spares.sav_vdevs) {
|
||||||
|
for (int i = 0; i < spa->spa_spares.sav_count; i++)
|
||||||
|
vdev_free(spa->spa_spares.sav_vdevs[i]);
|
||||||
kmem_free(spa->spa_spares.sav_vdevs,
|
kmem_free(spa->spa_spares.sav_vdevs,
|
||||||
spa->spa_spares.sav_count * sizeof (void *));
|
spa->spa_spares.sav_count * sizeof (void *));
|
||||||
spa->spa_spares.sav_vdevs = NULL;
|
spa->spa_spares.sav_vdevs = NULL;
|
||||||
|
@ -1727,11 +1727,11 @@ spa_unload(spa_t *spa)
|
||||||
}
|
}
|
||||||
spa->spa_spares.sav_count = 0;
|
spa->spa_spares.sav_count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
|
|
||||||
vdev_clear_stats(spa->spa_l2cache.sav_vdevs[i]);
|
|
||||||
vdev_free(spa->spa_l2cache.sav_vdevs[i]);
|
|
||||||
}
|
|
||||||
if (spa->spa_l2cache.sav_vdevs) {
|
if (spa->spa_l2cache.sav_vdevs) {
|
||||||
|
for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
|
||||||
|
vdev_clear_stats(spa->spa_l2cache.sav_vdevs[i]);
|
||||||
|
vdev_free(spa->spa_l2cache.sav_vdevs[i]);
|
||||||
|
}
|
||||||
kmem_free(spa->spa_l2cache.sav_vdevs,
|
kmem_free(spa->spa_l2cache.sav_vdevs,
|
||||||
spa->spa_l2cache.sav_count * sizeof (void *));
|
spa->spa_l2cache.sav_count * sizeof (void *));
|
||||||
spa->spa_l2cache.sav_vdevs = NULL;
|
spa->spa_l2cache.sav_vdevs = NULL;
|
||||||
|
@ -1789,20 +1789,21 @@ spa_load_spares(spa_t *spa)
|
||||||
/*
|
/*
|
||||||
* First, close and free any existing spare vdevs.
|
* First, close and free any existing spare vdevs.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < spa->spa_spares.sav_count; i++) {
|
if (spa->spa_spares.sav_vdevs) {
|
||||||
vd = spa->spa_spares.sav_vdevs[i];
|
for (i = 0; i < spa->spa_spares.sav_count; i++) {
|
||||||
|
vd = spa->spa_spares.sav_vdevs[i];
|
||||||
|
|
||||||
/* Undo the call to spa_activate() below */
|
/* Undo the call to spa_activate() below */
|
||||||
if ((tvd = spa_lookup_by_guid(spa, vd->vdev_guid,
|
if ((tvd = spa_lookup_by_guid(spa, vd->vdev_guid,
|
||||||
B_FALSE)) != NULL && tvd->vdev_isspare)
|
B_FALSE)) != NULL && tvd->vdev_isspare)
|
||||||
spa_spare_remove(tvd);
|
spa_spare_remove(tvd);
|
||||||
vdev_close(vd);
|
vdev_close(vd);
|
||||||
vdev_free(vd);
|
vdev_free(vd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spa->spa_spares.sav_vdevs)
|
|
||||||
kmem_free(spa->spa_spares.sav_vdevs,
|
kmem_free(spa->spa_spares.sav_vdevs,
|
||||||
spa->spa_spares.sav_count * sizeof (void *));
|
spa->spa_spares.sav_count * sizeof (void *));
|
||||||
|
}
|
||||||
|
|
||||||
if (spa->spa_spares.sav_config == NULL)
|
if (spa->spa_spares.sav_config == NULL)
|
||||||
nspares = 0;
|
nspares = 0;
|
||||||
|
@ -2013,23 +2014,24 @@ out:
|
||||||
/*
|
/*
|
||||||
* Purge vdevs that were dropped
|
* Purge vdevs that were dropped
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < oldnvdevs; i++) {
|
if (oldvdevs) {
|
||||||
uint64_t pool;
|
for (i = 0; i < oldnvdevs; i++) {
|
||||||
|
uint64_t pool;
|
||||||
|
|
||||||
vd = oldvdevs[i];
|
vd = oldvdevs[i];
|
||||||
if (vd != NULL) {
|
if (vd != NULL) {
|
||||||
ASSERT(vd->vdev_isl2cache);
|
ASSERT(vd->vdev_isl2cache);
|
||||||
|
|
||||||
if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
|
if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
|
||||||
pool != 0ULL && l2arc_vdev_present(vd))
|
pool != 0ULL && l2arc_vdev_present(vd))
|
||||||
l2arc_remove_vdev(vd);
|
l2arc_remove_vdev(vd);
|
||||||
vdev_clear_stats(vd);
|
vdev_clear_stats(vd);
|
||||||
vdev_free(vd);
|
vdev_free(vd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (oldvdevs)
|
|
||||||
kmem_free(oldvdevs, oldnvdevs * sizeof (void *));
|
kmem_free(oldvdevs, oldnvdevs * sizeof (void *));
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < sav->sav_count; i++)
|
for (i = 0; i < sav->sav_count; i++)
|
||||||
nvlist_free(l2cache[i]);
|
nvlist_free(l2cache[i]);
|
||||||
|
|
Loading…
Reference in New Issue