Skip to content

Commit 3805ae8

Browse files
alex-stetsenkoallanjude0mp
committed
Implement multiple dbuf eviction
Sponsored-by: Expensify, Inc. Sponsored-by: Klara, Inc. Co-authored-by: Allan Jude <[email protected]> Co-authored-by: Mateusz Piotrowski <[email protected]> Signed-off-by: Alexander Stetsenko <[email protected]> Signed-off-by: Allan Jude <[email protected]> Signed-off-by: Mateusz Piotrowski <[email protected]>
1 parent 919bc4d commit 3805ae8

File tree

1 file changed

+65
-31
lines changed

1 file changed

+65
-31
lines changed

module/zfs/dbuf.c

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -771,43 +771,77 @@ dbuf_cache_above_lowater(void)
771771
* Evict the oldest eligible dbuf from the dbuf cache.
772772
*/
773773
static void
774-
dbuf_evict_one(void)
774+
dbuf_evict_many(uint64_t bytes)
775775
{
776+
uint64_t evicted = 0;
777+
uint_t num_sublists = multilist_get_num_sublists(
778+
&dbuf_caches[DB_DBUF_CACHE].cache);
779+
776780
int idx = multilist_get_random_index(&dbuf_caches[DB_DBUF_CACHE].cache);
777-
multilist_sublist_t *mls = multilist_sublist_lock_idx(
778-
&dbuf_caches[DB_DBUF_CACHE].cache, idx);
781+
int start = idx;
779782

780-
ASSERT(!MUTEX_HELD(&dbuf_evict_lock));
783+
while (evicted < bytes && !dbuf_evict_thread_exit) {
784+
multilist_sublist_t *mls = multilist_sublist_lock_idx(
785+
&dbuf_caches[DB_DBUF_CACHE].cache, idx++);
781786

782-
dmu_buf_impl_t *db = multilist_sublist_tail(mls);
783-
while (db != NULL && mutex_tryenter(&db->db_mtx) == 0) {
784-
db = multilist_sublist_prev(mls, db);
785-
}
787+
ASSERT(!MUTEX_HELD(&dbuf_evict_lock));
786788

787-
DTRACE_PROBE2(dbuf__evict__one, dmu_buf_impl_t *, db,
788-
multilist_sublist_t *, mls);
789+
dmu_buf_impl_t *db = multilist_sublist_tail(mls);
790+
while (db != NULL && mutex_tryenter(&db->db_mtx) == 0) {
791+
db = multilist_sublist_prev(mls, db);
792+
}
789793

790-
if (db != NULL) {
791-
multilist_sublist_remove(mls, db);
792-
multilist_sublist_unlock(mls);
793-
uint64_t size = db->db.db_size;
794-
uint64_t usize = dmu_buf_user_size(&db->db);
795-
(void) zfs_refcount_remove_many(
796-
&dbuf_caches[DB_DBUF_CACHE].size, size, db);
797-
(void) zfs_refcount_remove_many(
798-
&dbuf_caches[DB_DBUF_CACHE].size, usize, db->db_user);
799-
DBUF_STAT_BUMPDOWN(cache_levels[db->db_level]);
800-
DBUF_STAT_BUMPDOWN(cache_count);
801-
DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size + usize);
802-
ASSERT3U(db->db_caching_status, ==, DB_DBUF_CACHE);
803-
db->db_caching_status = DB_NO_CACHE;
804-
dbuf_destroy(db);
805-
DBUF_STAT_BUMP(cache_total_evicts);
806-
} else {
807-
multilist_sublist_unlock(mls);
794+
if (db != NULL) {
795+
multilist_sublist_remove(mls, db);
796+
multilist_sublist_unlock(mls);
797+
798+
DTRACE_PROBE2(dbuf__evict__one, dmu_buf_impl_t *, db,
799+
multilist_sublist_t *, mls);
800+
801+
uint64_t size = db->db.db_size;
802+
uint64_t usize = dmu_buf_user_size(&db->db);
803+
804+
(void) zfs_refcount_remove_many(
805+
&dbuf_caches[DB_DBUF_CACHE].size, size, db);
806+
(void) zfs_refcount_remove_many(
807+
&dbuf_caches[DB_DBUF_CACHE].size, usize,
808+
db->db_user);
809+
810+
DBUF_STAT_BUMPDOWN(cache_levels[db->db_level]);
811+
DBUF_STAT_BUMPDOWN(cache_count);
812+
DBUF_STAT_DECR(cache_levels_bytes[db->db_level],
813+
size + usize);
814+
815+
ASSERT3U(db->db_caching_status, ==, DB_DBUF_CACHE);
816+
817+
db->db_caching_status = DB_NO_CACHE;
818+
dbuf_destroy(db);
819+
820+
DBUF_STAT_BUMP(cache_total_evicts);
821+
} else {
822+
multilist_sublist_unlock(mls);
823+
}
824+
825+
if (idx == start)
826+
break;
827+
828+
if (idx == num_sublists) /* wrap */
829+
idx = 0;
808830
}
809831
}
810832

833+
static void
834+
dbuf_evict(void)
835+
{
836+
int64_t bytes = (zfs_refcount_count(&dbuf_caches[DB_DBUF_CACHE].size) -
837+
dbuf_cache_lowater_bytes());
838+
839+
if (bytes <= 0)
840+
return;
841+
842+
dbuf_evict_many(bytes);
843+
}
844+
811845
/*
812846
* The dbuf evict thread is responsible for aging out dbufs from the
813847
* cache. Once the cache has reached it's maximum size, dbufs are removed
@@ -839,7 +873,7 @@ dbuf_evict_thread(void *unused)
839873
* minimize lock contention.
840874
*/
841875
while (dbuf_cache_above_lowater() && !dbuf_evict_thread_exit) {
842-
dbuf_evict_one();
876+
dbuf_evict();
843877
}
844878

845879
mutex_enter(&dbuf_evict_lock);
@@ -866,7 +900,7 @@ dbuf_evict_notify(uint64_t size)
866900
*/
867901
if (size > dbuf_cache_target_bytes()) {
868902
if (size > dbuf_cache_hiwater_bytes())
869-
dbuf_evict_one();
903+
dbuf_evict();
870904
cv_signal(&dbuf_evict_cv);
871905
}
872906
}
@@ -4106,7 +4140,7 @@ dmu_buf_rele(dmu_buf_t *db, const void *tag)
41064140
* dbuf_rele()-->dbuf_rele_and_unlock()-->dbuf_evict_notify()
41074141
* ^ |
41084142
* | |
4109-
* +-----dbuf_destroy()<--dbuf_evict_one()<--------+
4143+
* +-----dbuf_destroy()<--dbuf_evict()<--------+
41104144
*
41114145
*/
41124146
void

0 commit comments

Comments
 (0)