mirror of
https://git.proxmox.com/git/mirror_zfs
synced 2025-04-30 21:27:43 +00:00
Fix dspace underflow bug
Since spa_dspace accounts only normal allocation class space, spa_nonallocating_dspace should do the same. Otherwise we may get negative overflow or respective assertion spa_update_dspace() if removed special/dedup vdev is bigger than all normal class space. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Allan Jude <allan@klarasystems.com> Signed-off-by: Paul Dagnelie <paul.dagnelie@klarasystems.com> Closes #17183
This commit is contained in:
parent
11ca12dbd3
commit
367d34b3aa
@ -100,6 +100,7 @@ extern boolean_t vdev_replace_in_progress(vdev_t *vdev);
|
|||||||
extern void vdev_hold(vdev_t *);
|
extern void vdev_hold(vdev_t *);
|
||||||
extern void vdev_rele(vdev_t *);
|
extern void vdev_rele(vdev_t *);
|
||||||
|
|
||||||
|
void vdev_update_nonallocating_space(vdev_t *vd, boolean_t add);
|
||||||
extern int vdev_metaslab_init(vdev_t *vd, uint64_t txg);
|
extern int vdev_metaslab_init(vdev_t *vd, uint64_t txg);
|
||||||
extern void vdev_metaslab_fini(vdev_t *vd);
|
extern void vdev_metaslab_fini(vdev_t *vd);
|
||||||
extern void vdev_metaslab_set_size(vdev_t *);
|
extern void vdev_metaslab_set_size(vdev_t *);
|
||||||
|
@ -1515,6 +1515,25 @@ vdev_metaslab_group_create(vdev_t *vd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vdev_update_nonallocating_space(vdev_t *vd, boolean_t add)
|
||||||
|
{
|
||||||
|
spa_t *spa = vd->vdev_spa;
|
||||||
|
|
||||||
|
if (vd->vdev_mg->mg_class != spa_normal_class(spa))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t raw_space = metaslab_group_get_space(vd->vdev_mg);
|
||||||
|
uint64_t dspace = spa_deflate(spa) ?
|
||||||
|
vdev_deflated_space(vd, raw_space) : raw_space;
|
||||||
|
if (add) {
|
||||||
|
spa->spa_nonallocating_dspace += dspace;
|
||||||
|
} else {
|
||||||
|
ASSERT3U(spa->spa_nonallocating_dspace, >=, dspace);
|
||||||
|
spa->spa_nonallocating_dspace -= dspace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vdev_metaslab_init(vdev_t *vd, uint64_t txg)
|
vdev_metaslab_init(vdev_t *vd, uint64_t txg)
|
||||||
{
|
{
|
||||||
@ -1626,8 +1645,7 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg)
|
|||||||
*/
|
*/
|
||||||
if (vd->vdev_noalloc) {
|
if (vd->vdev_noalloc) {
|
||||||
/* track non-allocating vdev space */
|
/* track non-allocating vdev space */
|
||||||
spa->spa_nonallocating_dspace += spa_deflate(spa) ?
|
vdev_update_nonallocating_space(vd, B_TRUE);
|
||||||
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
|
|
||||||
} else if (!expanding) {
|
} else if (!expanding) {
|
||||||
metaslab_group_activate(vd->vdev_mg);
|
metaslab_group_activate(vd->vdev_mg);
|
||||||
if (vd->vdev_log_mg != NULL)
|
if (vd->vdev_log_mg != NULL)
|
||||||
|
@ -172,9 +172,6 @@ static void
|
|||||||
vdev_activate(vdev_t *vd)
|
vdev_activate(vdev_t *vd)
|
||||||
{
|
{
|
||||||
metaslab_group_t *mg = vd->vdev_mg;
|
metaslab_group_t *mg = vd->vdev_mg;
|
||||||
spa_t *spa = vd->vdev_spa;
|
|
||||||
uint64_t vdev_space = spa_deflate(spa) ?
|
|
||||||
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
|
|
||||||
|
|
||||||
ASSERT(!vd->vdev_islog);
|
ASSERT(!vd->vdev_islog);
|
||||||
ASSERT(vd->vdev_noalloc);
|
ASSERT(vd->vdev_noalloc);
|
||||||
@ -182,9 +179,7 @@ vdev_activate(vdev_t *vd)
|
|||||||
metaslab_group_activate(mg);
|
metaslab_group_activate(mg);
|
||||||
metaslab_group_activate(vd->vdev_log_mg);
|
metaslab_group_activate(vd->vdev_log_mg);
|
||||||
|
|
||||||
ASSERT3U(spa->spa_nonallocating_dspace, >=, vdev_space);
|
vdev_update_nonallocating_space(vd, B_FALSE);
|
||||||
|
|
||||||
spa->spa_nonallocating_dspace -= vdev_space;
|
|
||||||
|
|
||||||
vd->vdev_noalloc = B_FALSE;
|
vd->vdev_noalloc = B_FALSE;
|
||||||
}
|
}
|
||||||
@ -256,8 +251,7 @@ vdev_passivate(vdev_t *vd, uint64_t *txg)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
spa->spa_nonallocating_dspace += spa_deflate(spa) ?
|
vdev_update_nonallocating_space(vd, B_TRUE);
|
||||||
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
|
|
||||||
vd->vdev_noalloc = B_TRUE;
|
vd->vdev_noalloc = B_TRUE;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -1370,8 +1364,6 @@ vdev_remove_complete(spa_t *spa)
|
|||||||
ASSERT3P(vd->vdev_autotrim_thread, ==, NULL);
|
ASSERT3P(vd->vdev_autotrim_thread, ==, NULL);
|
||||||
vdev_rebuild_stop_wait(vd);
|
vdev_rebuild_stop_wait(vd);
|
||||||
ASSERT3P(vd->vdev_rebuild_thread, ==, NULL);
|
ASSERT3P(vd->vdev_rebuild_thread, ==, NULL);
|
||||||
uint64_t vdev_space = spa_deflate(spa) ?
|
|
||||||
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
|
|
||||||
|
|
||||||
sysevent_t *ev = spa_event_create(spa, vd, NULL,
|
sysevent_t *ev = spa_event_create(spa, vd, NULL,
|
||||||
ESC_ZFS_VDEV_REMOVE_DEV);
|
ESC_ZFS_VDEV_REMOVE_DEV);
|
||||||
@ -1379,11 +1371,8 @@ vdev_remove_complete(spa_t *spa)
|
|||||||
zfs_dbgmsg("finishing device removal for vdev %llu in txg %llu",
|
zfs_dbgmsg("finishing device removal for vdev %llu in txg %llu",
|
||||||
(u_longlong_t)vd->vdev_id, (u_longlong_t)txg);
|
(u_longlong_t)vd->vdev_id, (u_longlong_t)txg);
|
||||||
|
|
||||||
ASSERT3U(0, !=, vdev_space);
|
|
||||||
ASSERT3U(spa->spa_nonallocating_dspace, >=, vdev_space);
|
|
||||||
|
|
||||||
/* the vdev is no longer part of the dspace */
|
/* the vdev is no longer part of the dspace */
|
||||||
spa->spa_nonallocating_dspace -= vdev_space;
|
vdev_update_nonallocating_space(vd, B_FALSE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Discard allocation state.
|
* Discard allocation state.
|
||||||
|
Loading…
Reference in New Issue
Block a user