aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2023-06-09 19:40:55 +0000
committerGitHub <noreply@github.com>2023-06-09 19:40:55 +0000
commit70ea484e3ec56c529c6c5027ffc43840100ce224 (patch)
treed006081f0701728fe2b3a743cbd47e54e25fbac2
parent6db4ed51d6c2cd8ec6a3ad318118f7a0d6b6dfe8 (diff)
downloadsrc-70ea484e3ec56c529c6c5027ffc43840100ce224.tar.gz
src-70ea484e3ec56c529c6c5027ffc43840100ce224.zip
Finally drop long disabled vdev cache.
It was a vdev level read cache, designed to aggregate many small reads by speculatively issuing bigger reads instead and caching the result. But since it has almost no idea about what is going on with exception of ZIO_FLAG_DONT_CACHE flag set by higher layers, it was found to make more harm than good, for which reason it was disabled for the past 12 years. These days we have much better instruments to enlarge the I/Os, such as speculative and prescient prefetches, I/O scheduler, I/O aggregation etc. Besides just the dead code removal this removes one extra mutex lock/unlock per write inside vdev_cache_write(), not otherwise disabled and trying to do some work. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #14953
-rwxr-xr-xcmd/arc_summary35
-rw-r--r--cmd/zdb/zdb.c7
-rw-r--r--include/os/linux/kernel/linux/mod_compat.h1
-rw-r--r--include/sys/spa.h4
-rw-r--r--include/sys/vdev.h6
-rw-r--r--include/sys/vdev_impl.h20
-rw-r--r--include/sys/zio.h1
-rw-r--r--lib/libzpool/Makefile.am1
-rw-r--r--man/man4/zfs.415
-rw-r--r--man/man8/zpool-events.81
-rw-r--r--module/Kbuild.in1
-rw-r--r--module/Makefile.bsd1
-rw-r--r--module/os/freebsd/zfs/sysctl_os.c2
-rw-r--r--module/zfs/arc.c11
-rw-r--r--module/zfs/dmu_recv.c4
-rw-r--r--module/zfs/spa_misc.c2
-rw-r--r--module/zfs/vdev.c7
-rw-r--r--module/zfs/vdev_cache.c436
-rw-r--r--module/zfs/vdev_queue.c5
-rw-r--r--module/zfs/zio.c15
20 files changed, 13 insertions, 562 deletions
diff --git a/cmd/arc_summary b/cmd/arc_summary
index 6b29a611dab3..426e0207052d 100755
--- a/cmd/arc_summary
+++ b/cmd/arc_summary
@@ -64,7 +64,6 @@ SECTION_HELP = 'print info from one section ('+' '.join(SECTIONS)+')'
SECTION_PATHS = {'arc': 'arcstats',
'dmu': 'dmu_tx',
'l2arc': 'arcstats', # L2ARC stuff lives in arcstats
- 'vdev': 'vdev_cache_stats',
'zfetch': 'zfetchstats',
'zil': 'zil'}
@@ -90,8 +89,6 @@ if sys.platform.startswith('freebsd'):
# Requires py36-sysctl on FreeBSD
import sysctl
- VDEV_CACHE_SIZE = 'vdev.cache_size'
-
def is_value(ctl):
return ctl.type != sysctl.CTLTYPE_NODE
@@ -135,8 +132,6 @@ elif sys.platform.startswith('linux'):
SPL_PATH = '/sys/module/spl/parameters'
TUNABLES_PATH = '/sys/module/zfs/parameters'
- VDEV_CACHE_SIZE = 'zfs_vdev_cache_size'
-
def load_kstats(section):
path = os.path.join(KSTAT_PATH, section)
with open(path) as f:
@@ -952,35 +947,6 @@ def section_tunables(*_):
print()
-def section_vdev(kstats_dict):
- """Collect information on VDEV caches"""
-
- # Currently [Nov 2017] the VDEV cache is disabled, because it is actually
- # harmful. When this is the case, we just skip the whole entry. See
- # https://github.com/openzfs/zfs/blob/master/module/zfs/vdev_cache.c
- # for details
- tunables = get_vdev_params()
-
- if tunables[VDEV_CACHE_SIZE] == '0':
- print('VDEV cache disabled, skipping section\n')
- return
-
- vdev_stats = isolate_section('vdev_cache_stats', kstats_dict)
-
- vdev_cache_total = int(vdev_stats['hits']) +\
- int(vdev_stats['misses']) +\
- int(vdev_stats['delegations'])
-
- prt_1('VDEV cache summary:', f_hits(vdev_cache_total))
- prt_i2('Hit ratio:', f_perc(vdev_stats['hits'], vdev_cache_total),
- f_hits(vdev_stats['hits']))
- prt_i2('Miss ratio:', f_perc(vdev_stats['misses'], vdev_cache_total),
- f_hits(vdev_stats['misses']))
- prt_i2('Delegations:', f_perc(vdev_stats['delegations'], vdev_cache_total),
- f_hits(vdev_stats['delegations']))
- print()
-
-
def section_zil(kstats_dict):
"""Collect information on the ZFS Intent Log. Some of the information
taken from https://github.com/openzfs/zfs/blob/master/include/sys/zil.h
@@ -1008,7 +974,6 @@ section_calls = {'arc': section_arc,
'l2arc': section_l2arc,
'spl': section_spl,
'tunables': section_tunables,
- 'vdev': section_vdev,
'zil': section_zil}
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 105d36882291..04a10c4eedd7 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -8546,9 +8546,9 @@ zdb_read_block(char *thing, spa_t *spa)
*/
zio_nowait(zio_vdev_child_io(zio, bp, vd, offset, pabd,
psize, ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ,
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_PROPAGATE |
- ZIO_FLAG_DONT_RETRY | ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW |
- ZIO_FLAG_OPTIONAL, NULL, NULL));
+ ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW | ZIO_FLAG_OPTIONAL,
+ NULL, NULL));
}
error = zio_wait(zio);
@@ -8642,7 +8642,6 @@ zdb_read_block(char *thing, spa_t *spa)
zio_nowait(zio_vdev_child_io(czio, bp, vd,
offset, pabd, psize, ZIO_TYPE_READ,
ZIO_PRIORITY_SYNC_READ,
- ZIO_FLAG_DONT_CACHE |
ZIO_FLAG_DONT_PROPAGATE |
ZIO_FLAG_DONT_RETRY |
ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW |
diff --git a/include/os/linux/kernel/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h
index 09d109d191bf..8e20a9613539 100644
--- a/include/os/linux/kernel/linux/mod_compat.h
+++ b/include/os/linux/kernel/linux/mod_compat.h
@@ -68,7 +68,6 @@ enum scope_prefix_types {
zfs_trim,
zfs_txg,
zfs_vdev,
- zfs_vdev_cache,
zfs_vdev_file,
zfs_vdev_mirror,
zfs_vnops,
diff --git a/include/sys/spa.h b/include/sys/spa.h
index ed752967cca6..1fa2044008dc 100644
--- a/include/sys/spa.h
+++ b/include/sys/spa.h
@@ -1174,10 +1174,6 @@ extern void zep_to_zb(uint64_t dataset, zbookmark_err_phys_t *zep,
zbookmark_phys_t *zb);
extern void name_to_errphys(char *buf, zbookmark_err_phys_t *zep);
-/* vdev cache */
-extern void vdev_cache_stat_init(void);
-extern void vdev_cache_stat_fini(void);
-
/* vdev mirror */
extern void vdev_mirror_stat_init(void);
extern void vdev_mirror_stat_fini(void);
diff --git a/include/sys/vdev.h b/include/sys/vdev.h
index d529bbcdd9a4..26c834ff57cf 100644
--- a/include/sys/vdev.h
+++ b/include/sys/vdev.h
@@ -158,12 +158,6 @@ extern boolean_t vdev_allocatable(vdev_t *vd);
extern boolean_t vdev_accessible(vdev_t *vd, zio_t *zio);
extern boolean_t vdev_is_spacemap_addressable(vdev_t *vd);
-extern void vdev_cache_init(vdev_t *vd);
-extern void vdev_cache_fini(vdev_t *vd);
-extern boolean_t vdev_cache_read(zio_t *zio);
-extern void vdev_cache_write(zio_t *zio);
-extern void vdev_cache_purge(vdev_t *vd);
-
extern void vdev_queue_init(vdev_t *vd);
extern void vdev_queue_fini(vdev_t *vd);
extern zio_t *vdev_queue_io(zio_t *zio);
diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h
index ea3043c82a39..74b3737d8ee5 100644
--- a/include/sys/vdev_impl.h
+++ b/include/sys/vdev_impl.h
@@ -57,8 +57,6 @@ extern "C" {
* Forward declarations that lots of things need.
*/
typedef struct vdev_queue vdev_queue_t;
-typedef struct vdev_cache vdev_cache_t;
-typedef struct vdev_cache_entry vdev_cache_entry_t;
struct abd;
extern uint_t zfs_vdev_queue_depth_pct;
@@ -132,23 +130,6 @@ typedef const struct vdev_ops {
/*
* Virtual device properties
*/
-struct vdev_cache_entry {
- struct abd *ve_abd;
- uint64_t ve_offset;
- clock_t ve_lastused;
- avl_node_t ve_offset_node;
- avl_node_t ve_lastused_node;
- uint32_t ve_hits;
- uint16_t ve_missed_update;
- zio_t *ve_fill_io;
-};
-
-struct vdev_cache {
- avl_tree_t vc_offset_tree;
- avl_tree_t vc_lastused_tree;
- kmutex_t vc_lock;
-};
-
typedef struct vdev_queue_class {
uint32_t vqc_active;
@@ -443,7 +424,6 @@ struct vdev {
boolean_t vdev_resilver_deferred; /* resilver deferred */
boolean_t vdev_kobj_flag; /* kobj event record */
vdev_queue_t vdev_queue; /* I/O deadline schedule queue */
- vdev_cache_t vdev_cache; /* physical block cache */
spa_aux_vdev_t *vdev_aux; /* for l2cache and spares vdevs */
zio_t *vdev_probe_zio; /* root of current probe */
vdev_aux_t vdev_label_aux; /* on-disk aux state */
diff --git a/include/sys/zio.h b/include/sys/zio.h
index 695bc09e6cb7..6b1352a72b9a 100644
--- a/include/sys/zio.h
+++ b/include/sys/zio.h
@@ -190,7 +190,6 @@ typedef uint64_t zio_flag_t;
#define ZIO_FLAG_SPECULATIVE (1ULL << 8)
#define ZIO_FLAG_CONFIG_WRITER (1ULL << 9)
#define ZIO_FLAG_DONT_RETRY (1ULL << 10)
-#define ZIO_FLAG_DONT_CACHE (1ULL << 11)
#define ZIO_FLAG_NODATA (1ULL << 12)
#define ZIO_FLAG_INDUCE_DAMAGE (1ULL << 13)
#define ZIO_FLAG_IO_ALLOCATING (1ULL << 14)
diff --git a/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am
index ceac2963e647..58d7f07527aa 100644
--- a/lib/libzpool/Makefile.am
+++ b/lib/libzpool/Makefile.am
@@ -135,7 +135,6 @@ nodist_libzpool_la_SOURCES = \
module/zfs/uberblock.c \
module/zfs/unique.c \
module/zfs/vdev.c \
- module/zfs/vdev_cache.c \
module/zfs/vdev_draid.c \
module/zfs/vdev_draid_rand.c \
module/zfs/vdev_indirect.c \
diff --git a/man/man4/zfs.4 b/man/man4/zfs.4
index 9ec940a94488..5fbd9d7db93f 100644
--- a/man/man4/zfs.4
+++ b/man/man4/zfs.4
@@ -2028,21 +2028,6 @@ Max vdev I/O aggregation size.
.It Sy zfs_vdev_aggregation_limit_non_rotating Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq uint
Max vdev I/O aggregation size for non-rotating media.
.
-.It Sy zfs_vdev_cache_bshift Ns = Ns Sy 16 Po 64 KiB Pc Pq uint
-Shift size to inflate reads to.
-.
-.It Sy zfs_vdev_cache_max Ns = Ns Sy 16384 Ns B Po 16 KiB Pc Pq uint
-Inflate reads smaller than this value to meet the
-.Sy zfs_vdev_cache_bshift
-size
-.Pq default Sy 64 KiB .
-.
-.It Sy zfs_vdev_cache_size Ns = Ns Sy 0 Pq uint
-Total size of the per-disk cache in bytes.
-.Pp
-Currently this feature is disabled, as it has been found to not be helpful
-for performance and in some cases harmful.
-.
.It Sy zfs_vdev_mirror_rotating_inc Ns = Ns Sy 0 Pq int
A number by which the balancing algorithm increments the load calculation for
the purpose of selecting the least busy mirror member when an I/O operation
diff --git a/man/man8/zpool-events.8 b/man/man8/zpool-events.8
index 0ba93e4166e7..341f902fe66e 100644
--- a/man/man8/zpool-events.8
+++ b/man/man8/zpool-events.8
@@ -456,7 +456,6 @@ ZIO_FLAG_CANFAIL:0x00000080
ZIO_FLAG_SPECULATIVE:0x00000100
ZIO_FLAG_CONFIG_WRITER:0x00000200
ZIO_FLAG_DONT_RETRY:0x00000400
-ZIO_FLAG_DONT_CACHE:0x00000800
ZIO_FLAG_NODATA:0x00001000
ZIO_FLAG_INDUCE_DAMAGE:0x00002000
diff --git a/module/Kbuild.in b/module/Kbuild.in
index 29a55c9778b1..485331ac655e 100644
--- a/module/Kbuild.in
+++ b/module/Kbuild.in
@@ -382,7 +382,6 @@ ZFS_OBJS := \
uberblock.o \
unique.o \
vdev.o \
- vdev_cache.o \
vdev_draid.o \
vdev_draid_rand.o \
vdev_indirect.o \
diff --git a/module/Makefile.bsd b/module/Makefile.bsd
index 9464223f6ca6..0c4d8bfe1159 100644
--- a/module/Makefile.bsd
+++ b/module/Makefile.bsd
@@ -308,7 +308,6 @@ SRCS+= abd.c \
uberblock.c \
unique.c \
vdev.c \
- vdev_cache.c \
vdev_draid.c \
vdev_draid_rand.c \
vdev_indirect.c \
diff --git a/module/os/freebsd/zfs/sysctl_os.c b/module/os/freebsd/zfs/sysctl_os.c
index cc616f33db96..8ae2f23c3ecf 100644
--- a/module/os/freebsd/zfs/sysctl_os.c
+++ b/module/os/freebsd/zfs/sysctl_os.c
@@ -872,8 +872,6 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, validate_skip,
"Enable to bypass vdev_validate().");
/* END CSTYLED */
-/* vdev_cache.c */
-
/* vdev_mirror.c */
/* vdev_queue.c */
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index dcd4620fcd20..3dbaaa76b4a5 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -6106,8 +6106,7 @@ top:
asize, abd,
ZIO_CHECKSUM_OFF,
l2arc_read_done, cb, priority,
- zio_flags | ZIO_FLAG_DONT_CACHE |
- ZIO_FLAG_CANFAIL |
+ zio_flags | ZIO_FLAG_CANFAIL |
ZIO_FLAG_DONT_PROPAGATE |
ZIO_FLAG_DONT_RETRY, B_FALSE);
acb->acb_zio_head = rzio;
@@ -10177,8 +10176,7 @@ l2arc_dev_hdr_read(l2arc_dev_t *dev)
err = zio_wait(zio_read_phys(NULL, dev->l2ad_vdev,
VDEV_LABEL_START_SIZE, l2dhdr_asize, abd,
ZIO_CHECKSUM_LABEL, NULL, NULL, ZIO_PRIORITY_SYNC_READ,
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL |
- ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
ZIO_FLAG_SPECULATIVE, B_FALSE));
abd_free(abd);
@@ -10498,11 +10496,10 @@ l2arc_log_blk_fetch(vdev_t *vd, const l2arc_log_blkptr_t *lbp,
cb = kmem_zalloc(sizeof (l2arc_read_callback_t), KM_SLEEP);
cb->l2rcb_abd = abd_get_from_buf(lb, asize);
pio = zio_root(vd->vdev_spa, l2arc_blk_fetch_done, cb,
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE |
- ZIO_FLAG_DONT_RETRY);
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY);
(void) zio_nowait(zio_read_phys(pio, vd, lbp->lbp_daddr, asize,
cb->l2rcb_abd, ZIO_CHECKSUM_OFF, NULL, NULL,
- ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL |
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL |
ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY, B_FALSE));
return (pio);
diff --git a/module/zfs/dmu_recv.c b/module/zfs/dmu_recv.c
index c22a95f8647f..2fdd7c1ece73 100644
--- a/module/zfs/dmu_recv.c
+++ b/module/zfs/dmu_recv.c
@@ -1371,8 +1371,8 @@ do_corrective_recv(struct receive_writer_arg *rwa, struct drr_write *drrw,
dnode_t *dn;
abd_t *abd = rrd->abd;
zio_cksum_t bp_cksum = bp->blk_cksum;
- zio_flag_t flags = ZIO_FLAG_SPECULATIVE |
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_RETRY | ZIO_FLAG_CANFAIL;
+ zio_flag_t flags = ZIO_FLAG_SPECULATIVE | ZIO_FLAG_DONT_RETRY |
+ ZIO_FLAG_CANFAIL;
if (rwa->raw)
flags |= ZIO_FLAG_RAW;
diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c
index 014c539eb683..9ef948e9e434 100644
--- a/module/zfs/spa_misc.c
+++ b/module/zfs/spa_misc.c
@@ -2438,7 +2438,6 @@ spa_init(spa_mode_t mode)
zio_init();
dmu_init();
zil_init();
- vdev_cache_stat_init();
vdev_mirror_stat_init();
vdev_raidz_math_init();
vdev_file_init();
@@ -2462,7 +2461,6 @@ spa_fini(void)
spa_evict_all();
vdev_file_fini();
- vdev_cache_stat_fini();
vdev_mirror_stat_fini();
vdev_raidz_math_fini();
chksum_fini();
diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c
index 58dcd9f79799..612e66c3a8a8 100644
--- a/module/zfs/vdev.c
+++ b/module/zfs/vdev.c
@@ -715,7 +715,6 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
offsetof(struct vdev, vdev_dtl_node));
vd->vdev_stat.vs_timestamp = gethrtime();
vdev_queue_init(vd);
- vdev_cache_init(vd);
return (vd);
}
@@ -1096,7 +1095,6 @@ vdev_free(vdev_t *vd)
* Clean up vdev structure.
*/
vdev_queue_fini(vd);
- vdev_cache_fini(vd);
if (vd->vdev_path)
spa_strfree(vd->vdev_path);
@@ -1720,8 +1718,7 @@ vdev_probe(vdev_t *vd, zio_t *zio)
vps = kmem_zalloc(sizeof (*vps), KM_SLEEP);
vps->vps_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_PROBE |
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE |
- ZIO_FLAG_TRYHARD;
+ ZIO_FLAG_DONT_AGGREGATE | ZIO_FLAG_TRYHARD;
if (spa_config_held(spa, SCL_ZIO, RW_WRITER)) {
/*
@@ -2612,8 +2609,6 @@ vdev_close(vdev_t *vd)
vd->vdev_ops->vdev_op_close(vd);
- vdev_cache_purge(vd);
-
/*
* We record the previous state before we close it, so that if we are
* doing a reopen(), we don't generate FMA ereports if we notice that
diff --git a/module/zfs/vdev_cache.c b/module/zfs/vdev_cache.c
deleted file mode 100644
index f0a17600d58e..000000000000
--- a/module/zfs/vdev_cache.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or https://opensource.org/licenses/CDDL-1.0.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
- */
-
-#include <sys/zfs_context.h>
-#include <sys/spa.h>
-#include <sys/vdev_impl.h>
-#include <sys/zio.h>
-#include <sys/kstat.h>
-#include <sys/abd.h>
-
-/*
- * Virtual device read-ahead caching.
- *
- * This file implements a simple LRU read-ahead cache. When the DMU reads
- * a given block, it will often want other, nearby blocks soon thereafter.
- * We take advantage of this by reading a larger disk region and caching
- * the result. In the best case, this can turn 128 back-to-back 512-byte
- * reads into a single 64k read followed by 127 cache hits; this reduces
- * latency dramatically. In the worst case, it can turn an isolated 512-byte
- * read into a 64k read, which doesn't affect latency all that much but is
- * terribly wasteful of bandwidth. A more intelligent version of the cache
- * could keep track of access patterns and not do read-ahead unless it sees
- * at least two temporally close I/Os to the same region. Currently, only
- * metadata I/O is inflated. A further enhancement could take advantage of
- * more semantic information about the I/O. And it could use something
- * faster than an AVL tree; that was chosen solely for convenience.
- *
- * There are five cache operations: allocate, fill, read, write, evict.
- *
- * (1) Allocate. This reserves a cache entry for the specified region.
- * We separate the allocate and fill operations so that multiple threads
- * don't generate I/O for the same cache miss.
- *
- * (2) Fill. When the I/O for a cache miss completes, the fill routine
- * places the data in the previously allocated cache entry.
- *
- * (3) Read. Read data from the cache.
- *
- * (4) Write. Update cache contents after write completion.
- *
- * (5) Evict. When allocating a new entry, we evict the oldest (LRU) entry
- * if the total cache size exceeds zfs_vdev_cache_size.
- */
-
-/*
- * These tunables are for performance analysis.
- */
-/*
- * All i/os smaller than zfs_vdev_cache_max will be turned into
- * 1<<zfs_vdev_cache_bshift byte reads by the vdev_cache (aka software
- * track buffer). At most zfs_vdev_cache_size bytes will be kept in each
- * vdev's vdev_cache.
- *
- * TODO: Note that with the current ZFS code, it turns out that the
- * vdev cache is not helpful, and in some cases actually harmful. It
- * is better if we disable this. Once some time has passed, we should
- * actually remove this to simplify the code. For now we just disable
- * it by setting the zfs_vdev_cache_size to zero. Note that Solaris 11
- * has made these same changes.
- */
-static uint_t zfs_vdev_cache_max = 1 << 14; /* 16KB */
-static uint_t zfs_vdev_cache_size = 0;
-static uint_t zfs_vdev_cache_bshift = 16;
-
-#define VCBS (1 << zfs_vdev_cache_bshift) /* 64KB */
-
-static kstat_t *vdc_ksp = NULL;
-
-typedef struct vdc_stats {
- kstat_named_t vdc_stat_delegations;
- kstat_named_t vdc_stat_hits;
- kstat_named_t vdc_stat_misses;
-} vdc_stats_t;
-
-static vdc_stats_t vdc_stats = {
- { "delegations", KSTAT_DATA_UINT64 },
- { "hits", KSTAT_DATA_UINT64 },
- { "misses", KSTAT_DATA_UINT64 }
-};
-
-#define VDCSTAT_BUMP(stat) atomic_inc_64(&vdc_stats.stat.value.ui64);
-
-static inline int
-vdev_cache_offset_compare(const void *a1, const void *a2)
-{
- const vdev_cache_entry_t *ve1 = (const vdev_cache_entry_t *)a1;
- const vdev_cache_entry_t *ve2 = (const vdev_cache_entry_t *)a2;
-
- return (TREE_CMP(ve1->ve_offset, ve2->ve_offset));
-}
-
-static int
-vdev_cache_lastused_compare(const void *a1, const void *a2)
-{
- const vdev_cache_entry_t *ve1 = (const vdev_cache_entry_t *)a1;
- const vdev_cache_entry_t *ve2 = (const vdev_cache_entry_t *)a2;
-
- int cmp = TREE_CMP(ve1->ve_lastused, ve2->ve_lastused);
- if (likely(cmp))
- return (cmp);
-
- /*
- * Among equally old entries, sort by offset to ensure uniqueness.
- */
- return (vdev_cache_offset_compare(a1, a2));
-}
-
-/*
- * Evict the specified entry from the cache.
- */
-static void
-vdev_cache_evict(vdev_cache_t *vc, vdev_cache_entry_t *ve)
-{
- ASSERT(MUTEX_HELD(&vc->vc_lock));
- ASSERT3P(ve->ve_fill_io, ==, NULL);
- ASSERT3P(ve->ve_abd, !=, NULL);
-
- avl_remove(&vc->vc_lastused_tree, ve);
- avl_remove(&vc->vc_offset_tree, ve);
- abd_free(ve->ve_abd);
- kmem_free(ve, sizeof (vdev_cache_entry_t));
-}
-
-/*
- * Allocate an entry in the cache. At the point we don't have the data,
- * we're just creating a placeholder so that multiple threads don't all
- * go off and read the same blocks.
- */
-static vdev_cache_entry_t *
-vdev_cache_allocate(zio_t *zio)
-{
- vdev_cache_t *vc = &zio->io_vd->vdev_cache;
- uint64_t offset = P2ALIGN(zio->io_offset, VCBS);
- vdev_cache_entry_t *ve;
-
- ASSERT(MUTEX_HELD(&vc->vc_lock));
-
- if (zfs_vdev_cache_size == 0)
- return (NULL);
-
- /*
- * If adding a new entry would exceed the cache size,
- * evict the oldest entry (LRU).
- */
- if ((avl_numnodes(&vc->vc_lastused_tree) << zfs_vdev_cache_bshift) >
- zfs_vdev_cache_size) {
- ve = avl_first(&vc->vc_lastused_tree);
- if (ve->ve_fill_io != NULL)
- return (NULL);
- ASSERT3U(ve->ve_hits, !=, 0);
- vdev_cache_evict(vc, ve);
- }
-
- ve = kmem_zalloc(sizeof (vdev_cache_entry_t), KM_SLEEP);
- ve->ve_offset = offset;
- ve->ve_lastused = ddi_get_lbolt();
- ve->ve_abd = abd_alloc_for_io(VCBS, B_TRUE);
-
- avl_add(&vc->vc_offset_tree, ve);
- avl_add(&vc->vc_lastused_tree, ve);
-
- return (ve);
-}
-
-static void
-vdev_cache_hit(vdev_cache_t *vc, vdev_cache_entry_t *ve, zio_t *zio)
-{
- uint64_t cache_phase = P2PHASE(zio->io_offset, VCBS);
-
- ASSERT(MUTEX_HELD(&vc->vc_lock));
- ASSERT3P(ve->ve_fill_io, ==, NULL);
-
- if (ve->ve_lastused != ddi_get_lbolt()) {
- avl_remove(&vc->vc_lastused_tree, ve);
- ve->ve_lastused = ddi_get_lbolt();
- avl_add(&vc->vc_lastused_tree, ve);
- }
-
- ve->ve_hits++;
- abd_copy_off(zio->io_abd, ve->ve_abd, 0, cache_phase, zio->io_size);
-}
-
-/*
- * Fill a previously allocated cache entry with data.
- */
-static void
-vdev_cache_fill(zio_t *fio)
-{
- vdev_t *vd = fio->io_vd;
- vdev_cache_t *vc = &vd->vdev_cache;
- vdev_cache_entry_t *ve = fio->io_private;
- zio_t *pio;
-
- ASSERT3U(fio->io_size, ==, VCBS);
-
- /*
- * Add data to the cache.
- */
- mutex_enter(&vc->vc_lock);
-
- ASSERT3P(ve->ve_fill_io, ==, fio);
- ASSERT3U(ve->ve_offset, ==, fio->io_offset);
- ASSERT3P(ve->ve_abd, ==, fio->io_abd);
-
- ve->ve_fill_io = NULL;
-
- /*
- * Even if this cache line was invalidated by a missed write update,
- * any reads that were queued up before the missed update are still
- * valid, so we can satisfy them from this line before we evict it.
- */
- zio_link_t *zl = NULL;
- while ((pio = zio_walk_parents(fio, &zl)) != NULL)
- vdev_cache_hit(vc, ve, pio);
-
- if (fio->io_error || ve->ve_missed_update)
- vdev_cache_evict(vc, ve);
-
- mutex_exit(&vc->vc_lock);
-}
-
-/*
- * Read data from the cache. Returns B_TRUE cache hit, B_FALSE on miss.
- */
-boolean_t
-vdev_cache_read(zio_t *zio)
-{
- vdev_cache_t *vc = &zio->io_vd->vdev_cache;
- vdev_cache_entry_t *ve, ve_search;
- uint64_t cache_offset = P2ALIGN(zio->io_offset, VCBS);
- zio_t *fio;
- uint64_t cache_phase __maybe_unused = P2PHASE(zio->io_offset, VCBS);
-
- ASSERT3U(zio->io_type, ==, ZIO_TYPE_READ);
-
- if (zfs_vdev_cache_size == 0)
- return (B_FALSE);
-
- if (zio->io_flags & ZIO_FLAG_DONT_CACHE)
- return (B_FALSE);
-
- if (zio->io_size > zfs_vdev_cache_max)
- return (B_FALSE);
-
- /*
- * If the I/O straddles two or more cache blocks, don't cache it.
- */
- if (P2BOUNDARY(zio->io_offset, zio->io_size, VCBS))
- return (B_FALSE);
-
- ASSERT3U(cache_phase + zio->io_size, <=, VCBS);
-
- mutex_enter(&vc->vc_lock);
-
- ve_search.ve_offset = cache_offset;
- ve = avl_find(&vc->vc_offset_tree, &ve_search, NULL);
-
- if (ve != NULL) {
- if (ve->ve_missed_update) {
- mutex_exit(&vc->vc_lock);
- return (B_FALSE);
- }
-
- if ((fio = ve->ve_fill_io) != NULL) {
- zio_vdev_io_bypass(zio);
- zio_add_child(zio, fio);
- mutex_exit(&vc->vc_lock);
- VDCSTAT_BUMP(vdc_stat_delegations);
- return (B_TRUE);
- }
-
- vdev_cache_hit(vc, ve, zio);
- zio_vdev_io_bypass(zio);
-
- mutex_exit(&vc->vc_lock);
- VDCSTAT_BUMP(vdc_stat_hits);
- return (B_TRUE);
- }
-
- ve = vdev_cache_allocate(zio);
-
- if (ve == NULL) {
- mutex_exit(&vc->vc_lock);
- return (B_FALSE);
- }
-
- fio = zio_vdev_delegated_io(zio->io_vd, cache_offset,
- ve->ve_abd, VCBS, ZIO_TYPE_READ, ZIO_PRIORITY_NOW,
- ZIO_FLAG_DONT_CACHE, vdev_cache_fill, ve);
-
- ve->ve_fill_io = fio;
- zio_vdev_io_bypass(zio);
- zio_add_child(zio, fio);
-
- mutex_exit(&vc->vc_lock);
- zio_nowait(fio);
- VDCSTAT_BUMP(vdc_stat_misses);
-
- return (B_TRUE);
-}
-
-/*
- * Update cache contents upon write completion.
- */
-void
-vdev_cache_write(zio_t *zio)
-{
- vdev_cache_t *vc = &zio->io_vd->vdev_cache;
- vdev_cache_entry_t *ve, ve_search;
- uint64_t io_start = zio->io_offset;
- uint64_t io_end = io_start + zio->io_size;
- uint64_t min_offset = P2ALIGN(io_start, VCBS);
- uint64_t max_offset = P2ROUNDUP(io_end, VCBS);
- avl_index_t where;
-
- ASSERT3U(zio->io_type, ==, ZIO_TYPE_WRITE);
-
- mutex_enter(&vc->vc_lock);
-
- ve_search.ve_offset = min_offset;
- ve = avl_find(&vc->vc_offset_tree, &ve_search, &where);
-
- if (ve == NULL)
- ve = avl_nearest(&vc->vc_offset_tree, where, AVL_AFTER);
-
- while (ve != NULL && ve->ve_offset < max_offset) {
- uint64_t start = MAX(ve->ve_offset, io_start);
- uint64_t end = MIN(ve->ve_offset + VCBS, io_end);
-
- if (ve->ve_fill_io != NULL) {
- ve->ve_missed_update = 1;
- } else {
- abd_copy_off(ve->ve_abd, zio->io_abd,
- start - ve->ve_offset, start - io_start,
- end - start);
- }
- ve = AVL_NEXT(&vc->vc_offset_tree, ve);
- }
- mutex_exit(&vc->vc_lock);
-}
-
-void
-vdev_cache_purge(vdev_t *vd)
-{
- vdev_cache_t *vc = &vd->vdev_cache;
- vdev_cache_entry_t *ve;
-
- mutex_enter(&vc->vc_lock);
- while ((ve = avl_first(&vc->vc_offset_tree)) != NULL)
- vdev_cache_evict(vc, ve);
- mutex_exit(&vc->vc_lock);
-}
-
-void
-vdev_cache_init(vdev_t *vd)
-{
- vdev_cache_t *vc = &vd->vdev_cache;
-
- mutex_init(&vc->vc_lock, NULL, MUTEX_DEFAULT, NULL);
-
- avl_create(&vc->vc_offset_tree, vdev_cache_offset_compare,
- sizeof (vdev_cache_entry_t),
- offsetof(struct vdev_cache_entry, ve_offset_node));
-
- avl_create(&vc->vc_lastused_tree, vdev_cache_lastused_compare,
- sizeof (vdev_cache_entry_t),
- offsetof(struct vdev_cache_entry, ve_lastused_node));
-}
-
-void
-vdev_cache_fini(vdev_t *vd)
-{
- vdev_cache_t *vc = &vd->vdev_cache;
-
- vdev_cache_purge(vd);
-
- avl_destroy(&vc->vc_offset_tree);
- avl_destroy(&vc->vc_lastused_tree);
-
- mutex_destroy(&vc->vc_lock);
-}
-
-void
-vdev_cache_stat_init(void)
-{
- vdc_ksp = kstat_create("zfs", 0, "vdev_cache_stats", "misc",
- KSTAT_TYPE_NAMED, sizeof (vdc_stats) / sizeof (kstat_named_t),
- KSTAT_FLAG_VIRTUAL);
- if (vdc_ksp != NULL) {
- vdc_ksp->ks_data = &vdc_stats;
- kstat_install(vdc_ksp);
- }
-}
-
-void
-vdev_cache_stat_fini(void)
-{
- if (vdc_ksp != NULL) {
- kstat_delete(vdc_ksp);
- vdc_ksp = NULL;
- }
-}
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, cache_max, UINT, ZMOD_RW,
- "Inflate reads small than max");
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, cache_size, UINT, ZMOD_RD,
- "Total size of the per-disk cache");
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, cache_bshift, UINT, ZMOD_RW,
- "Shift size to inflate reads too");
diff --git a/module/zfs/vdev_queue.c b/module/zfs/vdev_queue.c
index 1a75d68abd9e..abb7d0662b8c 100644
--- a/module/zfs/vdev_queue.c
+++ b/module/zfs/vdev_queue.c
@@ -748,8 +748,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
aio = zio_vdev_delegated_io(first->io_vd, first->io_offset,
abd, size, first->io_type, zio->io_priority,
- flags | ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE,
- vdev_queue_agg_io_done, NULL);
+ flags | ZIO_FLAG_DONT_QUEUE, vdev_queue_agg_io_done, NULL);
aio->io_timestamp = first->io_timestamp;
nio = first;
@@ -907,7 +906,7 @@ vdev_queue_io(zio_t *zio)
ASSERT(zio->io_priority == ZIO_PRIORITY_TRIM);
}
- zio->io_flags |= ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE;
+ zio->io_flags |= ZIO_FLAG_DONT_QUEUE;
zio->io_timestamp = gethrtime();
mutex_enter(&vq->vq_lock);
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index c17ca5e1d651..d7b2217623e6 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -1617,12 +1617,6 @@ zio_read_bp_init(zio_t *zio)
ASSERT3P(zio->io_bp, ==, &zio->io_bp_copy);
}
- if (!DMU_OT_IS_METADATA(BP_GET_TYPE(bp)) && BP_GET_LEVEL(bp) == 0)
- zio->io_flags |= ZIO_FLAG_DONT_CACHE;
-
- if (BP_GET_TYPE(bp) == DMU_OT_DDT_ZAP)
- zio->io_flags |= ZIO_FLAG_DONT_CACHE;
-
if (BP_GET_DEDUP(bp) && zio->io_child_type == ZIO_CHILD_LOGICAL)
zio->io_pipeline = ZIO_DDT_READ_PIPELINE;
@@ -3955,9 +3949,6 @@ zio_vdev_io_start(zio_t *zio)
zio->io_type == ZIO_TYPE_WRITE ||
zio->io_type == ZIO_TYPE_TRIM)) {
- if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio))
- return (zio);
-
if ((zio = vdev_queue_io(zio)) == NULL)
return (NULL);
@@ -3994,9 +3985,6 @@ zio_vdev_io_done(zio_t *zio)
vd->vdev_ops != &vdev_draid_spare_ops) {
vdev_queue_io_done(zio);
- if (zio->io_type == ZIO_TYPE_WRITE)
- vdev_cache_write(zio);
-
if (zio_injection_enabled && zio->io_error == 0)
zio->io_error = zio_handle_device_injections(vd, zio,
EIO, EILSEQ);
@@ -4106,8 +4094,7 @@ zio_vdev_io_assess(zio_t *zio)
ASSERT(!(zio->io_flags & ZIO_FLAG_DONT_QUEUE)); /* not a leaf */
ASSERT(!(zio->io_flags & ZIO_FLAG_IO_BYPASS)); /* not a leaf */
zio->io_error = 0;
- zio->io_flags |= ZIO_FLAG_IO_RETRY |
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE;
+ zio->io_flags |= ZIO_FLAG_IO_RETRY | ZIO_FLAG_DONT_AGGREGATE;
zio->io_stage = ZIO_STAGE_VDEV_IO_START >> 1;
zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE,
zio_requeue_io_start_cut_in_line);