makefs/zfs: Allow the autotrim pool property to be set

Add an "autotrim" option taking "on" or "off". The value is stored in
the pool properties object alongside "bootfs", so the imported pool
starts trimming freed space automatically without a separate
"zpool set" step. When the option is omitted nothing is written and
the pool keeps the default ("off"), exactly as before.

A string option is used rather than makefs's boolean option type since
the latter ignores its value, which would make "autotrim=off" enable
the feature.

Define the spa_autotrim_t enumeration in the boot zfsimpl.h, copied
from OpenZFS's sys/spa.h, so that makefs can refer to SPA_AUTOTRIM_OFF
and SPA_AUTOTRIM_ON by name. The loader does not use it.

Document the option in makefs(8) and add a regression test.

Reviewed by:		markj
MFC after:		1 week
Sponsored by:		Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D60420
This commit is contained in:
R. Christian McDonald committed 2026-10-07 10:57:40 -04:00
1 parent fa6fe034a7
commit dece5b05f5
5 files changed
+98 -1

No files matched your search

+10
View File
@@ -904,6 +904,16 @@ typedef enum pool_state {
POOL_STATE_POTENTIALLY_ACTIVE /* Internal libzfs state */
} pool_state_t;
/*
* Send TRIM commands in-line during normal pool operation while deleting.
* OFF: no
* ON: yes
*/
typedef enum {
SPA_AUTOTRIM_OFF = 0,
SPA_AUTOTRIM_ON,
} spa_autotrim_t;
/*
* The uberblock version is incremented whenever an incompatible on-disk
* format change is made to the SPA, DMU, or ZAP.
+10 -1
View File
@@ -33,7 +33,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 12, 2026
.Dd October 7, 2026
.Dt MAKEFS 8
.Os
.Sh NAME
@@ -535,6 +535,15 @@ The following keywords are supported:
The base-2 logarithm of the minimum block size.
Typical values are 9 (512B blocks) and 12 (4KB blocks).
The default value is 12.
.It Cm autotrim
The value of the
.Ql autotrim
pool property, either
.Ql on
or
.Ql off .
The default is
.Ql off .
.It Cm bootfs
The name of the bootable dataset for the pool.
Specifying this option causes the
+59
View File
@@ -107,6 +107,64 @@ autoexpand_cleanup()
common_cleanup
}
#
# Test setting the autotrim pool property.
#
atf_test_case autotrim cleanup
autotrim_body()
{
local src val
create_test_inputs
atf_check -s exit:1 -e match:"invalid value .foo. for autotrim" \
$MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \
-o autotrim=foo $TEST_IMAGE $TEST_INPUTS_DIR
for val in on off; do
atf_check $MAKEFS -s 1g -o rootpath=/ \
-o poolname=$ZFS_POOL_NAME \
-o autotrim=$val \
$TEST_IMAGE $TEST_INPUTS_DIR
import_image
check_image_contents
# OpenZFS reports a pool property whose value equals the
# default as coming from the default, even if it was set.
if [ $val = off ]; then
src=default
else
src=local
fi
atf_check -o inline:$val\\n \
zpool get -H -o value autotrim $ZFS_POOL_NAME
atf_check -o inline:$src\\n \
zpool get -H -o source autotrim $ZFS_POOL_NAME
atf_check zpool destroy ${ZFS_POOL_NAME}
atf_check rm -f ${TEST_ZFS_POOL_NAME}
atf_check mdconfig -d -u $(cat ${TEST_MD_DEVICE_FILE})
atf_check rm -f ${TEST_MD_DEVICE_FILE}
done
# Without the option the property keeps its default value.
atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \
$TEST_IMAGE $TEST_INPUTS_DIR
import_image
atf_check -o inline:off\\n \
zpool get -H -o value autotrim $ZFS_POOL_NAME
atf_check -o inline:default\\n \
zpool get -H -o source autotrim $ZFS_POOL_NAME
}
autotrim_cleanup()
{
common_cleanup
}
#
# Test with some default layout defined by the common code.
#
@@ -1110,6 +1168,7 @@ T_flag_mtree_cleanup()
atf_init_test_cases()
{
atf_add_test_case autoexpand
atf_add_test_case autotrim
atf_add_test_case basic
atf_add_test_case compression
atf_add_test_case dataset_removal
+17
View File
@@ -82,6 +82,8 @@ zfs_prep_opts(fsinfo_t *fsopts)
memset(zfs, 0, sizeof(*zfs));
const option_t zfs_options[] = {
{ '\0', "autotrim", &zfs->autotrim, OPT_STRPTR,
0, 0, "Automatic TRIM (on or off)" },
{ '\0', "bootfs", &zfs->bootfs, OPT_STRPTR,
0, 0, "Bootable dataset" },
{ '\0', "mssize", &zfs->mssize, OPT_INT64,
@@ -247,6 +249,17 @@ zfs_check_opts(fsinfo_t *fsopts)
if (zfs->vdevpath[0] != '/')
errx(1, "path `%s' must be absolute", zfs->vdevpath);
zfs->autotrimval = SPA_AUTOTRIM_OFF;
if (zfs->autotrim != NULL) {
if (strcmp(zfs->autotrim, "on") == 0)
zfs->autotrimval = SPA_AUTOTRIM_ON;
else if (strcmp(zfs->autotrim, "off") == 0)
zfs->autotrimval = SPA_AUTOTRIM_OFF;
else
errx(1, "invalid value `%s' for autotrim",
zfs->autotrim);
}
if (zfs->ashift == 0)
zfs->ashift = 12;
@@ -262,6 +275,7 @@ zfs_cleanup_opts(fsinfo_t *fsopts)
zfs = fsopts->fs_specific;
free(zfs->rootpath);
free(zfs->vdevpath);
free(zfs->autotrim);
free(zfs->bootfs);
free(__DECONST(void *, zfs->poolname));
STAILQ_FOREACH_SAFE(d, &zfs->datasetdescs, next, tmp) {
@@ -474,6 +488,9 @@ pool_init_objdir_poolprops(zfs_opt_t *zfs, zfs_zap_t *objdir)
zap_add_uint64(objdir, DMU_POOL_PROPS, id);
zfs->poolprops = zap_alloc(zfs->mos, dnode);
if (zfs->autotrim != NULL)
zap_add_uint64(zfs->poolprops, "autotrim", zfs->autotrimval);
}
/*
+2
View File
@@ -80,6 +80,8 @@ typedef struct {
const char *poolname;
char *rootpath; /* implicit mount point prefix */
char *vdevpath; /* vdev path, pool property */
char *autotrim; /* "on" or "off", pool property */
spa_autotrim_t autotrimval; /* parsed autotrim value */
char *bootfs; /* bootable dataset, pool property */
int ashift; /* vdev block size */
uint64_t mssize; /* metaslab size */