Skip to content

Commit c9198ca

Browse files
pcd1193182robn
authored andcommitted
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 <[email protected]> Reviewed-by: Allan Jude <[email protected]> Signed-off-by: Paul Dagnelie <[email protected]> Closes #17183 (cherry picked from commit 367d34b)
1 parent c6b8138 commit c9198ca

File tree

3 files changed

+24
-16
lines changed

3 files changed

+24
-16
lines changed

include/sys/vdev.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ extern boolean_t vdev_replace_in_progress(vdev_t *vdev);
100100
extern void vdev_hold(vdev_t *);
101101
extern void vdev_rele(vdev_t *);
102102

103+
void vdev_update_nonallocating_space(vdev_t *vd, boolean_t add);
103104
extern int vdev_metaslab_init(vdev_t *vd, uint64_t txg);
104105
extern void vdev_metaslab_fini(vdev_t *vd);
105106
extern void vdev_metaslab_set_size(vdev_t *);

module/zfs/vdev.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,25 @@ vdev_metaslab_group_create(vdev_t *vd)
15161516
}
15171517
}
15181518

1519+
void
1520+
vdev_update_nonallocating_space(vdev_t *vd, boolean_t add)
1521+
{
1522+
spa_t *spa = vd->vdev_spa;
1523+
1524+
if (vd->vdev_mg->mg_class != spa_normal_class(spa))
1525+
return;
1526+
1527+
uint64_t raw_space = metaslab_group_get_space(vd->vdev_mg);
1528+
uint64_t dspace = spa_deflate(spa) ?
1529+
vdev_deflated_space(vd, raw_space) : raw_space;
1530+
if (add) {
1531+
spa->spa_nonallocating_dspace += dspace;
1532+
} else {
1533+
ASSERT3U(spa->spa_nonallocating_dspace, >=, dspace);
1534+
spa->spa_nonallocating_dspace -= dspace;
1535+
}
1536+
}
1537+
15191538
int
15201539
vdev_metaslab_init(vdev_t *vd, uint64_t txg)
15211540
{
@@ -1627,8 +1646,7 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg)
16271646
*/
16281647
if (vd->vdev_noalloc) {
16291648
/* track non-allocating vdev space */
1630-
spa->spa_nonallocating_dspace += spa_deflate(spa) ?
1631-
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
1649+
vdev_update_nonallocating_space(vd, B_TRUE);
16321650
} else if (!expanding) {
16331651
metaslab_group_activate(vd->vdev_mg);
16341652
if (vd->vdev_log_mg != NULL)

module/zfs/vdev_removal.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,14 @@ static void
172172
vdev_activate(vdev_t *vd)
173173
{
174174
metaslab_group_t *mg = vd->vdev_mg;
175-
spa_t *spa = vd->vdev_spa;
176-
uint64_t vdev_space = spa_deflate(spa) ?
177-
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
178175

179176
ASSERT(!vd->vdev_islog);
180177
ASSERT(vd->vdev_noalloc);
181178

182179
metaslab_group_activate(mg);
183180
metaslab_group_activate(vd->vdev_log_mg);
184181

185-
ASSERT3U(spa->spa_nonallocating_dspace, >=, vdev_space);
186-
187-
spa->spa_nonallocating_dspace -= vdev_space;
182+
vdev_update_nonallocating_space(vd, B_FALSE);
188183

189184
vd->vdev_noalloc = B_FALSE;
190185
}
@@ -256,8 +251,7 @@ vdev_passivate(vdev_t *vd, uint64_t *txg)
256251
return (error);
257252
}
258253

259-
spa->spa_nonallocating_dspace += spa_deflate(spa) ?
260-
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
254+
vdev_update_nonallocating_space(vd, B_TRUE);
261255
vd->vdev_noalloc = B_TRUE;
262256

263257
return (0);
@@ -1370,20 +1364,15 @@ vdev_remove_complete(spa_t *spa)
13701364
ASSERT3P(vd->vdev_autotrim_thread, ==, NULL);
13711365
vdev_rebuild_stop_wait(vd);
13721366
ASSERT3P(vd->vdev_rebuild_thread, ==, NULL);
1373-
uint64_t vdev_space = spa_deflate(spa) ?
1374-
vd->vdev_stat.vs_dspace : vd->vdev_stat.vs_space;
13751367

13761368
sysevent_t *ev = spa_event_create(spa, vd, NULL,
13771369
ESC_ZFS_VDEV_REMOVE_DEV);
13781370

13791371
zfs_dbgmsg("finishing device removal for vdev %llu in txg %llu",
13801372
(u_longlong_t)vd->vdev_id, (u_longlong_t)txg);
13811373

1382-
ASSERT3U(0, !=, vdev_space);
1383-
ASSERT3U(spa->spa_nonallocating_dspace, >=, vdev_space);
1384-
13851374
/* the vdev is no longer part of the dspace */
1386-
spa->spa_nonallocating_dspace -= vdev_space;
1375+
vdev_update_nonallocating_space(vd, B_FALSE);
13871376

13881377
/*
13891378
* Discard allocation state.

0 commit comments

Comments
 (0)