diff --git a/include/sys/dbuf.h b/include/sys/dbuf.h index d3d47f7ba..756459b2f 100644 --- a/include/sys/dbuf.h +++ b/include/sys/dbuf.h @@ -435,6 +435,7 @@ int dbuf_dnode_findbp(dnode_t *dn, uint64_t level, uint64_t blkid, void dbuf_init(void); void dbuf_fini(void); +void dbuf_cache_reduce_target_size(void); boolean_t dbuf_is_metadata(dmu_buf_impl_t *db); diff --git a/module/zfs/arc.c b/module/zfs/arc.c index ddb5b2686..c4c6e37c5 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -297,6 +297,7 @@ #include #include #include +#include #include #include #include @@ -4555,6 +4556,13 @@ arc_reduce_target_size(uint64_t to_free) to_free = 0; } + /* + * Since dbuf cache size is a fraction of target ARC size, we should + * notify dbuf about the reduction, which might be significant, + * especially if current ARC size was much smaller than the target. + */ + dbuf_cache_reduce_target_size(); + /* * Whether or not we reduced the target size, request eviction if the * current size is over it now, since caller obviously wants some RAM. diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index 81952af41..f94cfd726 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -872,6 +872,19 @@ dbuf_evict_notify(uint64_t size) } } +/* + * Since dbuf cache size is a fraction of target ARC size, ARC calls this when + * its target size is reduced due to memory pressure. + */ +void +dbuf_cache_reduce_target_size(void) +{ + uint64_t size = zfs_refcount_count(&dbuf_caches[DB_DBUF_CACHE].size); + + if (size > dbuf_cache_target_bytes()) + cv_signal(&dbuf_evict_cv); +} + static int dbuf_kstat_update(kstat_t *ksp, int rw) {