Add prefetch property

ZFS prefetch is currently governed by the zfs_prefetch_disable
tunable. However, this is a module-wide settings - if a specific
dataset benefits from prefetch, while others have issue with it,
an optimal solution does not exists.

This commit introduce the "prefetch" tri-state property, which enable
granular control (at dataset/volume level) for prefetching.

This patch does not remove the zfs_prefetch_disable, which remains
a system-wide switch for enable/disable prefetch. However, to avoid
duplication, it would be preferable to deprecate and then remove
the module tunable.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Ameer Hamza <ahamza@ixsystems.com>
Signed-off-by: Gionatan Danti <g.danti@assyoma.it>
Co-authored-by: Gionatan Danti <g.danti@assyoma.it>
Closes #15237 
Closes #15436
This commit is contained in:
Brian Behlendorf 2023-10-24 11:00:07 -07:00 committed by Tony Hutter
parent 706307445e
commit 61f3638a34
7 changed files with 63 additions and 2 deletions

View File

@ -132,6 +132,7 @@ struct objset {
zfs_logbias_op_t os_logbias; zfs_logbias_op_t os_logbias;
zfs_cache_type_t os_primary_cache; zfs_cache_type_t os_primary_cache;
zfs_cache_type_t os_secondary_cache; zfs_cache_type_t os_secondary_cache;
zfs_prefetch_type_t os_prefetch;
zfs_sync_type_t os_sync; zfs_sync_type_t os_sync;
zfs_redundant_metadata_type_t os_redundant_metadata; zfs_redundant_metadata_type_t os_redundant_metadata;
uint64_t os_recordsize; uint64_t os_recordsize;

View File

@ -191,6 +191,7 @@ typedef enum {
ZFS_PROP_REDACTED, ZFS_PROP_REDACTED,
ZFS_PROP_REDACT_SNAPS, ZFS_PROP_REDACT_SNAPS,
ZFS_PROP_SNAPSHOTS_CHANGED, ZFS_PROP_SNAPSHOTS_CHANGED,
ZFS_PROP_PREFETCH,
ZFS_NUM_PROPS ZFS_NUM_PROPS
} zfs_prop_t; } zfs_prop_t;
@ -546,6 +547,12 @@ typedef enum zfs_key_location {
ZFS_KEYLOCATION_LOCATIONS ZFS_KEYLOCATION_LOCATIONS
} zfs_keylocation_t; } zfs_keylocation_t;
typedef enum {
ZFS_PREFETCH_NONE = 0,
ZFS_PREFETCH_METADATA = 1,
ZFS_PREFETCH_ALL = 2
} zfs_prefetch_type_t;
#define DEFAULT_PBKDF2_ITERATIONS 350000 #define DEFAULT_PBKDF2_ITERATIONS 350000
#define MIN_PBKDF2_ITERATIONS 100000 #define MIN_PBKDF2_ITERATIONS 100000

View File

@ -1867,7 +1867,8 @@
<enumerator name='ZFS_PROP_REDACTED' value='93'/> <enumerator name='ZFS_PROP_REDACTED' value='93'/>
<enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/> <enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/>
<enumerator name='ZFS_PROP_SNAPSHOTS_CHANGED' value='95'/> <enumerator name='ZFS_PROP_SNAPSHOTS_CHANGED' value='95'/>
<enumerator name='ZFS_NUM_PROPS' value='96'/> <enumerator name='ZFS_PROP_PREFETCH' value='96'/>
<enumerator name='ZFS_NUM_PROPS' value='97'/>
</enum-decl> </enum-decl>
<typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/> <typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
<enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'> <enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>

View File

@ -1613,6 +1613,23 @@ If this property is set to
then only metadata is cached. then only metadata is cached.
The default value is The default value is
.Sy all . .Sy all .
.It Sy prefetch Ns = Ns Sy all Ns | Ns Sy none Ns | Ns Sy metadata
Controls what speculative prefetch does.
If this property is set to
.Sy all ,
then both user data and metadata are prefetched.
If this property is set to
.Sy none ,
then neither user data nor metadata are prefetched.
If this property is set to
.Sy metadata ,
then only metadata are prefetched.
The default value is
.Sy all .
.Pp
Please note that the module parameter zfs_disable_prefetch=1 can
be used to totally disable speculative prefetch, bypassing anything
this property does.
.It Sy setuid Ns = Ns Sy on Ns | Ns Sy off .It Sy setuid Ns = Ns Sy on Ns | Ns Sy off
Controls whether the setuid bit is respected for the file system. Controls whether the setuid bit is respected for the file system.
The default value is The default value is

View File

@ -345,6 +345,13 @@ zfs_prop_init(void)
{ NULL } { NULL }
}; };
static const zprop_index_t prefetch_table[] = {
{ "none", ZFS_PREFETCH_NONE },
{ "metadata", ZFS_PREFETCH_METADATA },
{ "all", ZFS_PREFETCH_ALL },
{ NULL }
};
static const zprop_index_t sync_table[] = { static const zprop_index_t sync_table[] = {
{ "standard", ZFS_SYNC_STANDARD }, { "standard", ZFS_SYNC_STANDARD },
{ "always", ZFS_SYNC_ALWAYS }, { "always", ZFS_SYNC_ALWAYS },
@ -453,6 +460,10 @@ zfs_prop_init(void)
ZFS_CACHE_ALL, PROP_INHERIT, ZFS_CACHE_ALL, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME,
"all | none | metadata", "SECONDARYCACHE", cache_table, sfeatures); "all | none | metadata", "SECONDARYCACHE", cache_table, sfeatures);
zprop_register_index(ZFS_PROP_PREFETCH, "prefetch",
ZFS_PREFETCH_ALL, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME,
"none | metadata | all", "PREFETCH", prefetch_table, sfeatures);
zprop_register_index(ZFS_PROP_LOGBIAS, "logbias", ZFS_LOGBIAS_LATENCY, zprop_register_index(ZFS_PROP_LOGBIAS, "logbias", ZFS_LOGBIAS_LATENCY,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"latency | throughput", "LOGBIAS", logbias_table, sfeatures); "latency | throughput", "LOGBIAS", logbias_table, sfeatures);

View File

@ -263,6 +263,19 @@ secondary_cache_changed_cb(void *arg, uint64_t newval)
os->os_secondary_cache = newval; os->os_secondary_cache = newval;
} }
static void
prefetch_changed_cb(void *arg, uint64_t newval)
{
objset_t *os = arg;
/*
* Inheritance should have been done by now.
*/
ASSERT(newval == ZFS_PREFETCH_ALL || newval == ZFS_PREFETCH_NONE ||
newval == ZFS_PREFETCH_METADATA);
os->os_prefetch = newval;
}
static void static void
sync_changed_cb(void *arg, uint64_t newval) sync_changed_cb(void *arg, uint64_t newval)
{ {
@ -562,6 +575,11 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE), zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE),
secondary_cache_changed_cb, os); secondary_cache_changed_cb, os);
} }
if (err == 0) {
err = dsl_prop_register(ds,
zfs_prop_to_name(ZFS_PROP_PREFETCH),
prefetch_changed_cb, os);
}
if (!ds->ds_is_snapshot) { if (!ds->ds_is_snapshot) {
if (err == 0) { if (err == 0) {
err = dsl_prop_register(ds, err = dsl_prop_register(ds,
@ -635,6 +653,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
os->os_primary_cache = ZFS_CACHE_ALL; os->os_primary_cache = ZFS_CACHE_ALL;
os->os_secondary_cache = ZFS_CACHE_ALL; os->os_secondary_cache = ZFS_CACHE_ALL;
os->os_dnodesize = DNODE_MIN_SIZE; os->os_dnodesize = DNODE_MIN_SIZE;
os->os_prefetch = ZFS_PREFETCH_ALL;
} }
if (ds == NULL || !ds->ds_is_snapshot) if (ds == NULL || !ds->ds_is_snapshot)

View File

@ -471,9 +471,14 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
{ {
zstream_t *zs; zstream_t *zs;
spa_t *spa = zf->zf_dnode->dn_objset->os_spa; spa_t *spa = zf->zf_dnode->dn_objset->os_spa;
zfs_prefetch_type_t os_prefetch = zf->zf_dnode->dn_objset->os_prefetch;
if (zfs_prefetch_disable) if (zfs_prefetch_disable || os_prefetch == ZFS_PREFETCH_NONE)
return (NULL); return (NULL);
if (os_prefetch == ZFS_PREFETCH_METADATA)
fetch_data = B_FALSE;
/* /*
* If we haven't yet loaded the indirect vdevs' mappings, we * If we haven't yet loaded the indirect vdevs' mappings, we
* can only read from blocks that we carefully ensure are on * can only read from blocks that we carefully ensure are on