mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
More adaptive ARC eviction
Traditionally ARC adaptation was limited to MRU/MFU distribution. But for years people with metadata-centric workload demanded mechanisms to also manage data/metadata distribution, that in original ZFS was just a FIFO. As result ZFS effectively got separate states for data and metadata, minimum and maximum metadata limits etc, but it all required manual tuning, was not adaptive and in its heart remained a bad FIFO. This change removes most of existing eviction logic, rewriting it from scratch. This makes MRU/MFU adaptation individual for data and meta- data, same as the distribution between data and metadata themselves. Since most of required states separation was already done, it only required to make arcs_size state field specific per data/metadata. The adaptation logic is still based on previous concept of ghost hits, just now it balances ARC capacity between 4 states: MRU data, MRU metadata, MFU data and MFU metadata. To simplify arc_c changes instead of arc_p measured in bytes, this code uses 3 variable arc_meta, arc_pd and arc_pm, representing ARC balance between metadata and data, MRU and MFU for data, and MRU and MFU for metadata respectively as 32-bit fixed point fractions. Since we care about the math result only when need to evict, this moves all the logic from arc_adapt() to arc_evict(), that reduces per-block overhead, since per-block operations are limited to stats collection, now moved from arc_adapt() to arc_access() and using cheaper wmsums. This also allows to remove ugly ARC_HDR_DO_ADAPT flag from many places. This change also removes number of metadata specific tunables, part of which were actually not functioning correctly, since not all metadata are equal and some (like L2ARC headers) are not really evictable. Instead it introduced single opaque knob zfs_arc_meta_balance, tuning ARC's reaction on ghost hits, allowing administrator give more or less preference to metadata without setting strict limits. Some of old code parts like arc_evict_meta() are just removed, because since introduction of ABD ARC they really make no sense: only headers referenced by small number of buffers are not evictable, and they are really not evictable no matter what this code do. Instead just call arc_prune_async() if too much metadata appear not evictable. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Allan Jude <allan@klarasystems.com> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #14359
This commit is contained in:
parent
8d9752569b
commit
a8d83e2a24
101
cmd/arc_summary
101
cmd/arc_summary
@ -270,16 +270,14 @@ def draw_graph(kstats_dict):
|
||||
arc_perc = f_perc(arc_stats['size'], arc_stats['c_max'])
|
||||
mfu_size = f_bytes(arc_stats['mfu_size'])
|
||||
mru_size = f_bytes(arc_stats['mru_size'])
|
||||
meta_limit = f_bytes(arc_stats['arc_meta_limit'])
|
||||
meta_size = f_bytes(arc_stats['arc_meta_used'])
|
||||
dnode_limit = f_bytes(arc_stats['arc_dnode_limit'])
|
||||
dnode_size = f_bytes(arc_stats['dnode_size'])
|
||||
|
||||
info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} ({5}) '
|
||||
'DNODE {6} ({7})')
|
||||
info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} '
|
||||
'DNODE {5} ({6})')
|
||||
info_line = info_form.format(arc_size, arc_perc, mfu_size, mru_size,
|
||||
meta_size, meta_limit, dnode_size,
|
||||
dnode_limit)
|
||||
meta_size, dnode_size, dnode_limit)
|
||||
info_spc = ' '*int((GRAPH_WIDTH-len(info_line))/2)
|
||||
info_line = GRAPH_INDENT+info_spc+info_line
|
||||
|
||||
@ -558,16 +556,28 @@ def section_arc(kstats_dict):
|
||||
arc_target_size = arc_stats['c']
|
||||
arc_max = arc_stats['c_max']
|
||||
arc_min = arc_stats['c_min']
|
||||
anon_size = arc_stats['anon_size']
|
||||
mfu_size = arc_stats['mfu_size']
|
||||
mru_size = arc_stats['mru_size']
|
||||
mfug_size = arc_stats['mfu_ghost_size']
|
||||
mrug_size = arc_stats['mru_ghost_size']
|
||||
unc_size = arc_stats['uncached_size']
|
||||
meta_limit = arc_stats['arc_meta_limit']
|
||||
meta_size = arc_stats['arc_meta_used']
|
||||
meta = arc_stats['meta']
|
||||
pd = arc_stats['pd']
|
||||
pm = arc_stats['pm']
|
||||
anon_data = arc_stats['anon_data']
|
||||
anon_metadata = arc_stats['anon_metadata']
|
||||
mfu_data = arc_stats['mfu_data']
|
||||
mfu_metadata = arc_stats['mfu_metadata']
|
||||
mru_data = arc_stats['mru_data']
|
||||
mru_metadata = arc_stats['mru_metadata']
|
||||
mfug_data = arc_stats['mfu_ghost_data']
|
||||
mfug_metadata = arc_stats['mfu_ghost_metadata']
|
||||
mrug_data = arc_stats['mru_ghost_data']
|
||||
mrug_metadata = arc_stats['mru_ghost_metadata']
|
||||
unc_data = arc_stats['uncached_data']
|
||||
unc_metadata = arc_stats['uncached_metadata']
|
||||
bonus_size = arc_stats['bonus_size']
|
||||
dnode_limit = arc_stats['arc_dnode_limit']
|
||||
dnode_size = arc_stats['dnode_size']
|
||||
dbuf_size = arc_stats['dbuf_size']
|
||||
hdr_size = arc_stats['hdr_size']
|
||||
l2_hdr_size = arc_stats['l2_hdr_size']
|
||||
abd_chunk_waste_size = arc_stats['abd_chunk_waste_size']
|
||||
target_size_ratio = '{0}:1'.format(int(arc_max) // int(arc_min))
|
||||
|
||||
prt_2('ARC size (current):',
|
||||
@ -578,25 +588,56 @@ def section_arc(kstats_dict):
|
||||
f_perc(arc_min, arc_max), f_bytes(arc_min))
|
||||
prt_i2('Max size (high water):',
|
||||
target_size_ratio, f_bytes(arc_max))
|
||||
caches_size = int(anon_size)+int(mfu_size)+int(mru_size)+int(unc_size)
|
||||
prt_i2('Anonymouns data size:',
|
||||
f_perc(anon_size, caches_size), f_bytes(anon_size))
|
||||
prt_i2('Most Frequently Used (MFU) cache size:',
|
||||
f_perc(mfu_size, caches_size), f_bytes(mfu_size))
|
||||
prt_i2('Most Recently Used (MRU) cache size:',
|
||||
f_perc(mru_size, caches_size), f_bytes(mru_size))
|
||||
prt_i1('Most Frequently Used (MFU) ghost size:', f_bytes(mfug_size))
|
||||
prt_i1('Most Recently Used (MRU) ghost size:', f_bytes(mrug_size))
|
||||
caches_size = int(anon_data)+int(anon_metadata)+\
|
||||
int(mfu_data)+int(mfu_metadata)+int(mru_data)+int(mru_metadata)+\
|
||||
int(unc_data)+int(unc_metadata)
|
||||
prt_i2('Anonymous data size:',
|
||||
f_perc(anon_data, caches_size), f_bytes(anon_data))
|
||||
prt_i2('Anonymous metadata size:',
|
||||
f_perc(anon_metadata, caches_size), f_bytes(anon_metadata))
|
||||
s = 4294967296
|
||||
v = (s-int(pd))*(s-int(meta))/s
|
||||
prt_i2('MFU data target:', f_perc(v, s),
|
||||
f_bytes(v / 65536 * caches_size / 65536))
|
||||
prt_i2('MFU data size:',
|
||||
f_perc(mfu_data, caches_size), f_bytes(mfu_data))
|
||||
prt_i1('MFU ghost data size:', f_bytes(mfug_data))
|
||||
v = (s-int(pm))*int(meta)/s
|
||||
prt_i2('MFU metadata target:', f_perc(v, s),
|
||||
f_bytes(v / 65536 * caches_size / 65536))
|
||||
prt_i2('MFU metadata size:',
|
||||
f_perc(mfu_metadata, caches_size), f_bytes(mfu_metadata))
|
||||
prt_i1('MFU ghost metadata size:', f_bytes(mfug_metadata))
|
||||
v = int(pd)*(s-int(meta))/s
|
||||
prt_i2('MRU data target:', f_perc(v, s),
|
||||
f_bytes(v / 65536 * caches_size / 65536))
|
||||
prt_i2('MRU data size:',
|
||||
f_perc(mru_data, caches_size), f_bytes(mru_data))
|
||||
prt_i1('MRU ghost data size:', f_bytes(mrug_data))
|
||||
v = int(pm)*int(meta)/s
|
||||
prt_i2('MRU metadata target:', f_perc(v, s),
|
||||
f_bytes(v / 65536 * caches_size / 65536))
|
||||
prt_i2('MRU metadata size:',
|
||||
f_perc(mru_metadata, caches_size), f_bytes(mru_metadata))
|
||||
prt_i1('MRU ghost metadata size:', f_bytes(mrug_metadata))
|
||||
prt_i2('Uncached data size:',
|
||||
f_perc(unc_size, caches_size), f_bytes(unc_size))
|
||||
prt_i2('Metadata cache size (hard limit):',
|
||||
f_perc(meta_limit, arc_max), f_bytes(meta_limit))
|
||||
prt_i2('Metadata cache size (current):',
|
||||
f_perc(meta_size, meta_limit), f_bytes(meta_size))
|
||||
prt_i2('Dnode cache size (hard limit):',
|
||||
f_perc(dnode_limit, meta_limit), f_bytes(dnode_limit))
|
||||
prt_i2('Dnode cache size (current):',
|
||||
f_perc(unc_data, caches_size), f_bytes(unc_data))
|
||||
prt_i2('Uncached metadata size:',
|
||||
f_perc(unc_metadata, caches_size), f_bytes(unc_metadata))
|
||||
prt_i2('Bonus size:',
|
||||
f_perc(bonus_size, arc_size), f_bytes(bonus_size))
|
||||
prt_i2('Dnode cache target:',
|
||||
f_perc(dnode_limit, arc_max), f_bytes(dnode_limit))
|
||||
prt_i2('Dnode cache size:',
|
||||
f_perc(dnode_size, dnode_limit), f_bytes(dnode_size))
|
||||
prt_i2('Dbuf size:',
|
||||
f_perc(dbuf_size, arc_size), f_bytes(dbuf_size))
|
||||
prt_i2('Header size:',
|
||||
f_perc(hdr_size, arc_size), f_bytes(hdr_size))
|
||||
prt_i2('L2 header size:',
|
||||
f_perc(l2_hdr_size, arc_size), f_bytes(l2_hdr_size))
|
||||
prt_i2('ABD chunk waste size:',
|
||||
f_perc(abd_chunk_waste_size, arc_size), f_bytes(abd_chunk_waste_size))
|
||||
print()
|
||||
|
||||
print('ARC hash breakdown:')
|
||||
|
@ -117,7 +117,6 @@ zdb_ot_name(dmu_object_type_t type)
|
||||
|
||||
extern int reference_tracking_enable;
|
||||
extern int zfs_recover;
|
||||
extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit;
|
||||
extern uint_t zfs_vdev_async_read_max_active;
|
||||
extern boolean_t spa_load_verify_dryrun;
|
||||
extern boolean_t spa_mode_readable_spacemaps;
|
||||
@ -8809,8 +8808,8 @@ main(int argc, char **argv)
|
||||
* ZDB does not typically re-read blocks; therefore limit the ARC
|
||||
* to 256 MB, which can be used entirely for metadata.
|
||||
*/
|
||||
zfs_arc_min = zfs_arc_meta_min = 2ULL << SPA_MAXBLOCKSHIFT;
|
||||
zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024;
|
||||
zfs_arc_min = 2ULL << SPA_MAXBLOCKSHIFT;
|
||||
zfs_arc_max = 256 * 1024 * 1024;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -200,7 +200,6 @@ struct arc_buf {
|
||||
};
|
||||
|
||||
typedef enum arc_buf_contents {
|
||||
ARC_BUFC_INVALID, /* invalid type */
|
||||
ARC_BUFC_DATA, /* buffer contains data */
|
||||
ARC_BUFC_METADATA, /* buffer contains metadata */
|
||||
ARC_BUFC_NUMTYPES
|
||||
|
@ -82,15 +82,18 @@ typedef struct arc_state {
|
||||
* supports the "dbufs" kstat
|
||||
*/
|
||||
arc_state_type_t arcs_state;
|
||||
/*
|
||||
* total amount of data in this state.
|
||||
*/
|
||||
zfs_refcount_t arcs_size[ARC_BUFC_NUMTYPES] ____cacheline_aligned;
|
||||
/*
|
||||
* total amount of evictable data in this state
|
||||
*/
|
||||
zfs_refcount_t arcs_esize[ARC_BUFC_NUMTYPES] ____cacheline_aligned;
|
||||
zfs_refcount_t arcs_esize[ARC_BUFC_NUMTYPES];
|
||||
/*
|
||||
* total amount of data in this state; this includes: evictable,
|
||||
* non-evictable, ARC_BUFC_DATA, and ARC_BUFC_METADATA.
|
||||
* amount of hit bytes for this state (counted only for ghost states)
|
||||
*/
|
||||
zfs_refcount_t arcs_size;
|
||||
wmsum_t arcs_hits[ARC_BUFC_NUMTYPES];
|
||||
} arc_state_t;
|
||||
|
||||
typedef struct arc_callback arc_callback_t;
|
||||
@ -358,8 +361,9 @@ typedef struct l2arc_lb_ptr_buf {
|
||||
#define L2BLK_SET_PREFETCH(field, x) BF64_SET((field), 39, 1, x)
|
||||
#define L2BLK_GET_CHECKSUM(field) BF64_GET((field), 40, 8)
|
||||
#define L2BLK_SET_CHECKSUM(field, x) BF64_SET((field), 40, 8, x)
|
||||
#define L2BLK_GET_TYPE(field) BF64_GET((field), 48, 8)
|
||||
#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, x)
|
||||
/* +/- 1 here are to keep compatibility after ARC_BUFC_INVALID removal. */
|
||||
#define L2BLK_GET_TYPE(field) (BF64_GET((field), 48, 8) - 1)
|
||||
#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, (x) + 1)
|
||||
#define L2BLK_GET_PROTECTED(field) BF64_GET((field), 56, 1)
|
||||
#define L2BLK_SET_PROTECTED(field, x) BF64_SET((field), 56, 1, x)
|
||||
#define L2BLK_GET_STATE(field) BF64_GET((field), 57, 4)
|
||||
@ -582,7 +586,9 @@ typedef struct arc_stats {
|
||||
kstat_named_t arcstat_hash_collisions;
|
||||
kstat_named_t arcstat_hash_chains;
|
||||
kstat_named_t arcstat_hash_chain_max;
|
||||
kstat_named_t arcstat_p;
|
||||
kstat_named_t arcstat_meta;
|
||||
kstat_named_t arcstat_pd;
|
||||
kstat_named_t arcstat_pm;
|
||||
kstat_named_t arcstat_c;
|
||||
kstat_named_t arcstat_c_min;
|
||||
kstat_named_t arcstat_c_max;
|
||||
@ -655,6 +661,8 @@ typedef struct arc_stats {
|
||||
* are all included in this value.
|
||||
*/
|
||||
kstat_named_t arcstat_anon_size;
|
||||
kstat_named_t arcstat_anon_data;
|
||||
kstat_named_t arcstat_anon_metadata;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that meet the
|
||||
* following criteria: backing buffers of type ARC_BUFC_DATA,
|
||||
@ -676,6 +684,8 @@ typedef struct arc_stats {
|
||||
* are all included in this value.
|
||||
*/
|
||||
kstat_named_t arcstat_mru_size;
|
||||
kstat_named_t arcstat_mru_data;
|
||||
kstat_named_t arcstat_mru_metadata;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that meet the
|
||||
* following criteria: backing buffers of type ARC_BUFC_DATA,
|
||||
@ -700,6 +710,8 @@ typedef struct arc_stats {
|
||||
* buffers *would have* consumed this number of bytes.
|
||||
*/
|
||||
kstat_named_t arcstat_mru_ghost_size;
|
||||
kstat_named_t arcstat_mru_ghost_data;
|
||||
kstat_named_t arcstat_mru_ghost_metadata;
|
||||
/*
|
||||
* Number of bytes that *would have been* consumed by ARC
|
||||
* buffers that are eligible for eviction, of type
|
||||
@ -719,6 +731,8 @@ typedef struct arc_stats {
|
||||
* are all included in this value.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_size;
|
||||
kstat_named_t arcstat_mfu_data;
|
||||
kstat_named_t arcstat_mfu_metadata;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that are eligible for
|
||||
* eviction, of type ARC_BUFC_DATA, and reside in the arc_mfu
|
||||
@ -737,6 +751,8 @@ typedef struct arc_stats {
|
||||
* arcstat_mru_ghost_size for more details.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_ghost_size;
|
||||
kstat_named_t arcstat_mfu_ghost_data;
|
||||
kstat_named_t arcstat_mfu_ghost_metadata;
|
||||
/*
|
||||
* Number of bytes that *would have been* consumed by ARC
|
||||
* buffers that are eligible for eviction, of type
|
||||
@ -754,6 +770,8 @@ typedef struct arc_stats {
|
||||
* ARC_FLAG_UNCACHED being set.
|
||||
*/
|
||||
kstat_named_t arcstat_uncached_size;
|
||||
kstat_named_t arcstat_uncached_data;
|
||||
kstat_named_t arcstat_uncached_metadata;
|
||||
/*
|
||||
* Number of data bytes that are going to be evicted from ARC due to
|
||||
* ARC_FLAG_UNCACHED being set.
|
||||
@ -876,10 +894,7 @@ typedef struct arc_stats {
|
||||
kstat_named_t arcstat_loaned_bytes;
|
||||
kstat_named_t arcstat_prune;
|
||||
kstat_named_t arcstat_meta_used;
|
||||
kstat_named_t arcstat_meta_limit;
|
||||
kstat_named_t arcstat_dnode_limit;
|
||||
kstat_named_t arcstat_meta_max;
|
||||
kstat_named_t arcstat_meta_min;
|
||||
kstat_named_t arcstat_async_upgrade_sync;
|
||||
/* Number of predictive prefetch requests. */
|
||||
kstat_named_t arcstat_predictive_prefetch;
|
||||
@ -942,7 +957,7 @@ typedef struct arc_sums {
|
||||
wmsum_t arcstat_data_size;
|
||||
wmsum_t arcstat_metadata_size;
|
||||
wmsum_t arcstat_dbuf_size;
|
||||
aggsum_t arcstat_dnode_size;
|
||||
wmsum_t arcstat_dnode_size;
|
||||
wmsum_t arcstat_bonus_size;
|
||||
wmsum_t arcstat_l2_hits;
|
||||
wmsum_t arcstat_l2_misses;
|
||||
@ -987,7 +1002,7 @@ typedef struct arc_sums {
|
||||
wmsum_t arcstat_memory_direct_count;
|
||||
wmsum_t arcstat_memory_indirect_count;
|
||||
wmsum_t arcstat_prune;
|
||||
aggsum_t arcstat_meta_used;
|
||||
wmsum_t arcstat_meta_used;
|
||||
wmsum_t arcstat_async_upgrade_sync;
|
||||
wmsum_t arcstat_predictive_prefetch;
|
||||
wmsum_t arcstat_demand_hit_predictive_prefetch;
|
||||
@ -1015,7 +1030,9 @@ typedef struct arc_evict_waiter {
|
||||
#define ARCSTAT_BUMPDOWN(stat) ARCSTAT_INCR(stat, -1)
|
||||
|
||||
#define arc_no_grow ARCSTAT(arcstat_no_grow) /* do not grow cache size */
|
||||
#define arc_p ARCSTAT(arcstat_p) /* target size of MRU */
|
||||
#define arc_meta ARCSTAT(arcstat_meta) /* target frac of metadata */
|
||||
#define arc_pd ARCSTAT(arcstat_pd) /* target frac of data MRU */
|
||||
#define arc_pm ARCSTAT(arcstat_pm) /* target frac of meta MRU */
|
||||
#define arc_c ARCSTAT(arcstat_c) /* target size of cache */
|
||||
#define arc_c_min ARCSTAT(arcstat_c_min) /* min target cache size */
|
||||
#define arc_c_max ARCSTAT(arcstat_c_max) /* max target cache size */
|
||||
|
@ -558,14 +558,6 @@ This value acts as a ceiling to the amount of dnode metadata, and defaults to
|
||||
which indicates that a percent which is based on
|
||||
.Sy zfs_arc_dnode_limit_percent
|
||||
of the ARC meta buffers that may be used for dnodes.
|
||||
.Pp
|
||||
Also see
|
||||
.Sy zfs_arc_meta_prune
|
||||
which serves a similar purpose but is used
|
||||
when the amount of metadata in the ARC exceeds
|
||||
.Sy zfs_arc_meta_limit
|
||||
rather than in response to overall demand for non-metadata.
|
||||
.
|
||||
.It Sy zfs_arc_dnode_limit_percent Ns = Ns Sy 10 Ns % Pq u64
|
||||
Percentage that can be consumed by dnodes of ARC meta buffers.
|
||||
.Pp
|
||||
@ -648,62 +640,10 @@ It cannot be set back to
|
||||
while running, and reducing it below the current ARC size will not cause
|
||||
the ARC to shrink without memory pressure to induce shrinking.
|
||||
.
|
||||
.It Sy zfs_arc_meta_adjust_restarts Ns = Ns Sy 4096 Pq uint
|
||||
The number of restart passes to make while scanning the ARC attempting
|
||||
the free buffers in order to stay below the
|
||||
.Sy fs_arc_meta_limit .
|
||||
This value should not need to be tuned but is available to facilitate
|
||||
performance analysis.
|
||||
.
|
||||
.It Sy zfs_arc_meta_limit Ns = Ns Sy 0 Ns B Pq u64
|
||||
The maximum allowed size in bytes that metadata buffers are allowed to
|
||||
consume in the ARC.
|
||||
When this limit is reached, metadata buffers will be reclaimed,
|
||||
even if the overall
|
||||
.Sy arc_c_max
|
||||
has not been reached.
|
||||
It defaults to
|
||||
.Sy 0 ,
|
||||
which indicates that a percentage based on
|
||||
.Sy zfs_arc_meta_limit_percent
|
||||
of the ARC may be used for metadata.
|
||||
.Pp
|
||||
This value my be changed dynamically, except that must be set to an explicit
|
||||
value
|
||||
.Pq cannot be set back to Sy 0 .
|
||||
.
|
||||
.It Sy zfs_arc_meta_limit_percent Ns = Ns Sy 75 Ns % Pq u64
|
||||
Percentage of ARC buffers that can be used for metadata.
|
||||
.Pp
|
||||
See also
|
||||
.Sy zfs_arc_meta_limit ,
|
||||
which serves a similar purpose but has a higher priority if nonzero.
|
||||
.
|
||||
.It Sy zfs_arc_meta_min Ns = Ns Sy 0 Ns B Pq u64
|
||||
The minimum allowed size in bytes that metadata buffers may consume in
|
||||
the ARC.
|
||||
.
|
||||
.It Sy zfs_arc_meta_prune Ns = Ns Sy 10000 Pq int
|
||||
The number of dentries and inodes to be scanned looking for entries
|
||||
which can be dropped.
|
||||
This may be required when the ARC reaches the
|
||||
.Sy zfs_arc_meta_limit
|
||||
because dentries and inodes can pin buffers in the ARC.
|
||||
Increasing this value will cause to dentry and inode caches
|
||||
to be pruned more aggressively.
|
||||
Setting this value to
|
||||
.Sy 0
|
||||
will disable pruning the inode and dentry caches.
|
||||
.
|
||||
.It Sy zfs_arc_meta_strategy Ns = Ns Sy 1 Ns | Ns 0 Pq uint
|
||||
Define the strategy for ARC metadata buffer eviction (meta reclaim strategy):
|
||||
.Bl -tag -compact -offset 4n -width "0 (META_ONLY)"
|
||||
.It Sy 0 Pq META_ONLY
|
||||
evict only the ARC metadata buffers
|
||||
.It Sy 1 Pq BALANCED
|
||||
additional data buffers may be evicted if required
|
||||
to evict the required number of metadata buffers.
|
||||
.El
|
||||
.It Sy zfs_arc_meta_balance Ns = Ns Sy 500 Pq uint
|
||||
Balance between metadata and data on ghost hits.
|
||||
Values above 100 increase metadata caching by proportionally reducing effect
|
||||
of ghost data hits on target data/metadata rate.
|
||||
.
|
||||
.It Sy zfs_arc_min Ns = Ns Sy 0 Ns B Pq u64
|
||||
Min size of ARC in bytes.
|
||||
@ -786,20 +726,6 @@ causes the ARC to start reclamation if it exceeds the target size by
|
||||
of the target size, and block allocations by
|
||||
.Em 0.6% .
|
||||
.
|
||||
.It Sy zfs_arc_p_min_shift Ns = Ns Sy 0 Pq uint
|
||||
If nonzero, this will update
|
||||
.Sy arc_p_min_shift Pq default Sy 4
|
||||
with the new value.
|
||||
.Sy arc_p_min_shift No is used as a shift of Sy arc_c
|
||||
when calculating the minumum
|
||||
.Sy arc_p No size .
|
||||
.
|
||||
.It Sy zfs_arc_p_dampener_disable Ns = Ns Sy 1 Ns | Ns 0 Pq int
|
||||
Disable
|
||||
.Sy arc_p
|
||||
adapt dampener, which reduces the maximum single adjustment to
|
||||
.Sy arc_p .
|
||||
.
|
||||
.It Sy zfs_arc_shrink_shift Ns = Ns Sy 0 Pq uint
|
||||
If nonzero, this will update
|
||||
.Sy arc_shrink_shift Pq default Sy 7
|
||||
|
@ -159,7 +159,7 @@ arc_prune_task(void *arg)
|
||||
/*
|
||||
* Notify registered consumers they must drop holds on a portion of the ARC
|
||||
* buffered they reference. This provides a mechanism to ensure the ARC can
|
||||
* honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This
|
||||
* honor the metadata limit and reclaim otherwise pinned ARC buffers. This
|
||||
* is analogous to dnlc_reduce_cache() but more generic.
|
||||
*
|
||||
* This operation is performed asynchronously so it may be safely called
|
||||
|
@ -359,89 +359,114 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_norw,
|
||||
"No reads during writes (LEGACY)");
|
||||
/* END CSTYLED */
|
||||
|
||||
static int
|
||||
param_get_arc_state_size(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
arc_state_t *state = (arc_state_t *)arg1;
|
||||
int64_t val;
|
||||
|
||||
val = zfs_refcount_count(&state->arcs_size[ARC_BUFC_DATA]) +
|
||||
zfs_refcount_count(&state->arcs_size[ARC_BUFC_METADATA]);
|
||||
return (sysctl_handle_64(oidp, &val, 0, req));
|
||||
}
|
||||
|
||||
extern arc_state_t ARC_anon;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_size, CTLFLAG_RD,
|
||||
&ARC_anon.arcs_size.rc_count, 0, "size of anonymous state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, anon_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_anon, 0, param_get_arc_state_size, "Q",
|
||||
"size of anonymous state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_metadata_esize, CTLFLAG_RD,
|
||||
&ARC_anon.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
|
||||
"size of metadata in anonymous state");
|
||||
"size of evictable metadata in anonymous state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_data_esize, CTLFLAG_RD,
|
||||
&ARC_anon.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
|
||||
"size of data in anonymous state");
|
||||
"size of evictable data in anonymous state");
|
||||
/* END CSTYLED */
|
||||
|
||||
extern arc_state_t ARC_mru;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_size, CTLFLAG_RD,
|
||||
&ARC_mru.arcs_size.rc_count, 0, "size of mru state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, mru_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_mru, 0, param_get_arc_state_size, "Q",
|
||||
"size of mru state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_metadata_esize, CTLFLAG_RD,
|
||||
&ARC_mru.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
|
||||
"size of metadata in mru state");
|
||||
"size of evictable metadata in mru state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_data_esize, CTLFLAG_RD,
|
||||
&ARC_mru.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
|
||||
"size of data in mru state");
|
||||
"size of evictable data in mru state");
|
||||
/* END CSTYLED */
|
||||
|
||||
extern arc_state_t ARC_mru_ghost;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_size, CTLFLAG_RD,
|
||||
&ARC_mru_ghost.arcs_size.rc_count, 0, "size of mru ghost state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, mru_ghost_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_mru_ghost, 0, param_get_arc_state_size, "Q",
|
||||
"size of mru ghost state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_metadata_esize, CTLFLAG_RD,
|
||||
&ARC_mru_ghost.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
|
||||
"size of metadata in mru ghost state");
|
||||
"size of evictable metadata in mru ghost state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_data_esize, CTLFLAG_RD,
|
||||
&ARC_mru_ghost.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
|
||||
"size of data in mru ghost state");
|
||||
"size of evictable data in mru ghost state");
|
||||
/* END CSTYLED */
|
||||
|
||||
extern arc_state_t ARC_mfu;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_size, CTLFLAG_RD,
|
||||
&ARC_mfu.arcs_size.rc_count, 0, "size of mfu state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, mfu_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_mfu, 0, param_get_arc_state_size, "Q",
|
||||
"size of mfu state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_metadata_esize, CTLFLAG_RD,
|
||||
&ARC_mfu.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
|
||||
"size of metadata in mfu state");
|
||||
"size of evictable metadata in mfu state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_data_esize, CTLFLAG_RD,
|
||||
&ARC_mfu.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
|
||||
"size of data in mfu state");
|
||||
"size of evictable data in mfu state");
|
||||
/* END CSTYLED */
|
||||
|
||||
extern arc_state_t ARC_mfu_ghost;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_size, CTLFLAG_RD,
|
||||
&ARC_mfu_ghost.arcs_size.rc_count, 0, "size of mfu ghost state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, mfu_ghost_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_mfu_ghost, 0, param_get_arc_state_size, "Q",
|
||||
"size of mfu ghost state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_metadata_esize, CTLFLAG_RD,
|
||||
&ARC_mfu_ghost.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
|
||||
"size of metadata in mfu ghost state");
|
||||
"size of evictable metadata in mfu ghost state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_data_esize, CTLFLAG_RD,
|
||||
&ARC_mfu_ghost.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
|
||||
"size of data in mfu ghost state");
|
||||
"size of evictable data in mfu ghost state");
|
||||
/* END CSTYLED */
|
||||
|
||||
extern arc_state_t ARC_uncached;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, uncached_size, CTLFLAG_RD,
|
||||
&ARC_uncached.arcs_size.rc_count, 0, "size of uncached state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, uncached_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_uncached, 0, param_get_arc_state_size, "Q",
|
||||
"size of uncached state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, uncached_metadata_esize, CTLFLAG_RD,
|
||||
&ARC_uncached.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
|
||||
"size of metadata in uncached state");
|
||||
"size of evictable metadata in uncached state");
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, uncached_data_esize, CTLFLAG_RD,
|
||||
&ARC_uncached.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
|
||||
"size of data in uncached state");
|
||||
"size of evictable data in uncached state");
|
||||
/* END CSTYLED */
|
||||
|
||||
extern arc_state_t ARC_l2c_only;
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2c_only_size, CTLFLAG_RD,
|
||||
&ARC_l2c_only.arcs_size.rc_count, 0, "size of mru state");
|
||||
SYSCTL_PROC(_vfs_zfs, OID_AUTO, l2c_only_size,
|
||||
CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
&ARC_l2c_only, 0, param_get_arc_state_size, "Q",
|
||||
"size of l2c_only state");
|
||||
/* END CSTYLED */
|
||||
|
||||
/* dbuf.c */
|
||||
|
@ -504,7 +504,7 @@ arc_prune_task(void *ptr)
|
||||
/*
|
||||
* Notify registered consumers they must drop holds on a portion of the ARC
|
||||
* buffered they reference. This provides a mechanism to ensure the ARC can
|
||||
* honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This
|
||||
* honor the metadata limit and reclaim otherwise pinned ARC buffers. This
|
||||
* is analogous to dnlc_reduce_cache() but more generic.
|
||||
*
|
||||
* This operation is performed asynchronously so it may be safely called
|
||||
|
941
module/zfs/arc.c
941
module/zfs/arc.c
File diff suppressed because it is too large
Load Diff
@ -485,7 +485,6 @@ function get_system_config
|
||||
printf " \"tunables\": {\n" >>$config
|
||||
for tunable in \
|
||||
zfs_arc_max \
|
||||
zfs_arc_meta_limit \
|
||||
zfs_arc_sys_free \
|
||||
zfs_dirty_data_max \
|
||||
zfs_flags \
|
||||
|
Loading…
Reference in New Issue
Block a user