]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Add prefetch property
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 24 Oct 2023 18:00:07 +0000 (11:00 -0700)
committerGitHub <noreply@github.com>
Tue, 24 Oct 2023 18:00:07 +0000 (11:00 -0700)
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

include/sys/dmu_objset.h
include/sys/fs/zfs.h
lib/libzfs/libzfs.abi
man/man7/zfsprops.7
module/zcommon/zfs_prop.c
module/zfs/dmu_objset.c
module/zfs/dmu_zfetch.c

index 9f6e0fdd601be49539ca512df10b6863ea5297cc..a9123e862af79e6f307a151b20aafac77e88b586 100644 (file)
@@ -132,6 +132,7 @@ struct objset {
        zfs_logbias_op_t os_logbias;
        zfs_cache_type_t os_primary_cache;
        zfs_cache_type_t os_secondary_cache;
+       zfs_prefetch_type_t os_prefetch;
        zfs_sync_type_t os_sync;
        zfs_redundant_metadata_type_t os_redundant_metadata;
        uint64_t os_recordsize;
index bc940e8a79296548a470c24bdf00b210bacf54e8..9d7eca9784b60aa791cc8b1175d7fca83d9cb778 100644 (file)
@@ -191,6 +191,7 @@ typedef enum {
        ZFS_PROP_REDACTED,
        ZFS_PROP_REDACT_SNAPS,
        ZFS_PROP_SNAPSHOTS_CHANGED,
+       ZFS_PROP_PREFETCH,
        ZFS_NUM_PROPS
 } zfs_prop_t;
 
@@ -543,6 +544,12 @@ typedef enum zfs_key_location {
        ZFS_KEYLOCATION_LOCATIONS
 } 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        MIN_PBKDF2_ITERATIONS 100000
 
index c1ce3d0f67d8b7cf99b78a5b9b77fb864e6ff0a4..083c27be7d31c111ed0c50a5af75fc443ffc4b90 100644 (file)
       <enumerator name='ZFS_PROP_REDACTED' value='93'/>
       <enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/>
       <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>
     <typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
     <enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>
index e3674b1f8a8d7caf8e143f825c729f4c0abf2696..59f6404379afd5e81dcfc0b018219ec91ce2ebc6 100644 (file)
@@ -1613,6 +1613,23 @@ If this property is set to
 then only metadata is cached.
 The default value is
 .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
 Controls whether the setuid bit is respected for the file system.
 The default value is
index 3db6fd13f4ae240d16fa2f5e2ea3cb769ad1b08d..29764674a31b9454ab02ed6dbc5042c3de69492a 100644 (file)
@@ -345,6 +345,13 @@ zfs_prop_init(void)
                { 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[] = {
                { "standard",   ZFS_SYNC_STANDARD },
                { "always",     ZFS_SYNC_ALWAYS },
@@ -453,6 +460,10 @@ zfs_prop_init(void)
            ZFS_CACHE_ALL, PROP_INHERIT,
            ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME,
            "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,
            PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
            "latency | throughput", "LOGBIAS", logbias_table, sfeatures);
index d134d4958f7cda707eae6f022ece764d0f87fa71..76e65b5506a96ddea296a3dcf8afc57a929aa069 100644 (file)
@@ -263,6 +263,19 @@ secondary_cache_changed_cb(void *arg, uint64_t 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
 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),
                            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 (err == 0) {
                                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_secondary_cache = ZFS_CACHE_ALL;
                os->os_dnodesize = DNODE_MIN_SIZE;
+               os->os_prefetch = ZFS_PREFETCH_ALL;
        }
 
        if (ds == NULL || !ds->ds_is_snapshot)
index d0acaf5020664b0c8e31c3160edc8131d4d013a9..2b2d72671001661391c7636337c205d436297fd3 100644 (file)
@@ -329,9 +329,14 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
 {
        zstream_t *zs;
        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);
+
+       if (os_prefetch == ZFS_PREFETCH_METADATA)
+               fetch_data = B_FALSE;
+
        /*
         * If we haven't yet loaded the indirect vdevs' mappings, we
         * can only read from blocks that we carefully ensure are on