Skip to content

Commit 2f8c9bd

Browse files
committed
Tighten up 'zpool remove' space check
The available space check in spa_vdev_remove_top_check() is intended to verify there is enough available space on the other devices before starting the removal process. This is obviously a good idea but the current check can significantly overestimate the space requirements for small pools preventing removal when it clearly should be possible. This change reworks the check to drop the additional slop space from the calculation. This solves two problems: 1) If a large device is accidentally added to a small pool the slop requirement is dramatically increased. This in turn can prevent removal of that larger device even if it has never been used. This was particularly unfortunate since a main motivation for this feature was to allow such mistakes to be corrected. 2) For very small pools with 256M vdevs the minimum slop size of 128M represents a huge fraction of the total pool capacity. Requiring twice this amount of space to be available effectively prevents device removal from ever working with these tiny pools. Signed-off-by: Brian Behlendorf <[email protected]> Issue #11356
1 parent d5a5ec4 commit 2f8c9bd

File tree

5 files changed

+126
-11
lines changed

5 files changed

+126
-11
lines changed

module/zfs/vdev_removal.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,17 +2003,18 @@ spa_vdev_remove_top_check(vdev_t *vd)
20032003
if (available < vd->vdev_stat.vs_alloc)
20042004
return (SET_ERROR(ENOSPC));
20052005
} else {
2006-
/* available space in the pool's normal class */
2006+
/*
2007+
* This is a normal device. There has to be enough free
2008+
* space in the pool's normal class to remove the device
2009+
* and leave 1.6% of the space available. The available
2010+
* space accounts for both reserved and "slop" space.
2011+
*/
20072012
uint64_t available = dsl_dir_space_available(
20082013
spa->spa_dsl_pool->dp_root_dir, NULL, 0, B_TRUE);
2009-
if (available <
2010-
vd->vdev_stat.vs_dspace + spa_get_slop_space(spa)) {
2011-
/*
2012-
* This is a normal device. There has to be enough free
2013-
* space to remove the device and leave double the
2014-
* "slop" space (i.e. we must leave at least 3% of the
2015-
* pool free, in addition to the normal slop space).
2016-
*/
2014+
2015+
if (available < vd->vdev_stat.vs_dspace ||
2016+
available - vd->vdev_stat.vs_dspace <
2017+
spa_get_dspace(spa) >> 6) {
20172018
return (SET_ERROR(ENOSPC));
20182019
}
20192020
}

tests/runfiles/common.run

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,8 @@ tests = ['removal_all_vdev', 'removal_cancel', 'removal_check_space',
784784
'removal_with_send_recv', 'removal_with_snapshot',
785785
'removal_with_write', 'removal_with_zdb', 'remove_expanded',
786786
'remove_mirror', 'remove_mirror_sanity', 'remove_raidz',
787-
'remove_indirect', 'remove_attach_mirror']
787+
'remove_indirect', 'remove_attach_mirror', 'remove_minimum',
788+
'remove_unbalanced']
788789
tags = ['functional', 'removal']
789790

790791
[tests/functional/rename_dirs]

tests/zfs-tests/tests/functional/removal/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dist_pkgdata_SCRIPTS = \
3030
removal_with_snapshot.ksh removal_with_write.ksh \
3131
removal_with_zdb.ksh remove_mirror.ksh remove_mirror_sanity.ksh \
3232
remove_raidz.ksh remove_expanded.ksh remove_indirect.ksh \
33-
remove_attach_mirror.ksh
33+
remove_attach_mirror.ksh remove_minimum.ksh remove_unbalanced.ksh
3434

3535
dist_pkgdata_DATA = \
3636
removal.kshlib
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/bin/ksh -p
2+
#
3+
# CDDL HEADER START
4+
#
5+
# This file and its contents are supplied under the terms of the
6+
# Common Development and Distribution License ("CDDL"), version 1.0.
7+
# You may only use this file in accordance with the terms of version
8+
# 1.0 of the CDDL.
9+
#
10+
# A full copy of the text of the CDDL should have accompanied this
11+
# source. A copy of the CDDL is also available via the Internet at
12+
# http://www.illumos.org/license/CDDL.
13+
#
14+
# CDDL HEADER END
15+
#
16+
17+
#
18+
# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
19+
#
20+
21+
. $STF_SUITE/include/libtest.shlib
22+
. $STF_SUITE/tests/functional/removal/removal.kshlib
23+
24+
#
25+
# DESCRIPTION:
26+
# Device removal is possible for minimum sized vdevs.
27+
#
28+
# STRATEGY:
29+
# 1. Create a pool with minimum sized removable devices
30+
# 2. Remove a top-level device
31+
#
32+
33+
verify_runnable "global"
34+
35+
function cleanup
36+
{
37+
default_cleanup_noexit
38+
log_must rm -f $TEST_BASE_DIR/device-{1,2}
39+
}
40+
41+
log_assert "Device removal is possible for minimum sized vdevs."
42+
log_onexit cleanup
43+
44+
# 1. Create a pool with minimum sized removable devices
45+
log_must truncate -s $MINVDEVSIZE $TEST_BASE_DIR/device-{1,2}
46+
log_must default_setup_noexit "$TEST_BASE_DIR/device-1 $TEST_BASE_DIR/device-2"
47+
48+
log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=1M count=64
49+
50+
# 2. Remove a top-level device
51+
log_must zpool remove $TESTPOOL $TEST_BASE_DIR/device-1
52+
log_must wait_for_removal $TESTPOOL
53+
54+
log_note "Capacity $(get_pool_prop capacity $TESTPOOL)"
55+
56+
log_pass "Device removal is possible for minimum sized vdevs"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/ksh -p
2+
#
3+
# CDDL HEADER START
4+
#
5+
# This file and its contents are supplied under the terms of the
6+
# Common Development and Distribution License ("CDDL"), version 1.0.
7+
# You may only use this file in accordance with the terms of version
8+
# 1.0 of the CDDL.
9+
#
10+
# A full copy of the text of the CDDL should have accompanied this
11+
# source. A copy of the CDDL is also available via the Internet at
12+
# http://www.illumos.org/license/CDDL.
13+
#
14+
# CDDL HEADER END
15+
#
16+
17+
#
18+
# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
19+
#
20+
21+
. $STF_SUITE/include/libtest.shlib
22+
. $STF_SUITE/tests/functional/removal/removal.kshlib
23+
24+
#
25+
# DESCRIPTION:
26+
# Device removal is possible for highly unbalanced vdevs.
27+
#
28+
# STRATEGY:
29+
# 1. Create a pool with unbalanced removable devices
30+
# 2. Remove the large top-level device
31+
#
32+
33+
verify_runnable "global"
34+
35+
function cleanup
36+
{
37+
default_cleanup_noexit
38+
log_must rm -f $TEST_BASE_DIR/device-{1,2}
39+
}
40+
41+
log_assert "Device removal is possible for highly unbalanced vdevs."
42+
log_onexit cleanup
43+
44+
# 1. Create a pool with unbalanced removable devices
45+
log_must truncate -s 10G $TEST_BASE_DIR/device-1
46+
log_must truncate -s 1T $TEST_BASE_DIR/device-2
47+
log_must default_setup_noexit "$TEST_BASE_DIR/device-1 $TEST_BASE_DIR/device-2"
48+
49+
log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=1M count=32
50+
51+
# 2. Remove the large top-level device
52+
log_must zpool remove $TESTPOOL $TEST_BASE_DIR/device-1
53+
log_must wait_for_removal $TESTPOOL
54+
55+
log_note "Capacity $(get_pool_prop capacity $TESTPOOL)"
56+
57+
log_pass "Device removal is possible for highly unbalanced vdevs"

0 commit comments

Comments
 (0)