@@ -771,43 +771,77 @@ dbuf_cache_above_lowater(void)
771
771
* Evict the oldest eligible dbuf from the dbuf cache.
772
772
*/
773
773
static void
774
- dbuf_evict_one ( void )
774
+ dbuf_evict_many ( uint64_t bytes )
775
775
{
776
+ uint64_t evicted = 0 ;
777
+ uint_t num_sublists = multilist_get_num_sublists (
778
+ & dbuf_caches [DB_DBUF_CACHE ].cache );
779
+
776
780
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 ;
779
782
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 ++ );
781
786
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 ));
786
788
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
+ }
789
793
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 ;
808
830
}
809
831
}
810
832
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
+
811
845
/*
812
846
* The dbuf evict thread is responsible for aging out dbufs from the
813
847
* cache. Once the cache has reached it's maximum size, dbufs are removed
@@ -839,7 +873,7 @@ dbuf_evict_thread(void *unused)
839
873
* minimize lock contention.
840
874
*/
841
875
while (dbuf_cache_above_lowater () && !dbuf_evict_thread_exit ) {
842
- dbuf_evict_one ();
876
+ dbuf_evict ();
843
877
}
844
878
845
879
mutex_enter (& dbuf_evict_lock );
@@ -866,7 +900,7 @@ dbuf_evict_notify(uint64_t size)
866
900
*/
867
901
if (size > dbuf_cache_target_bytes ()) {
868
902
if (size > dbuf_cache_hiwater_bytes ())
869
- dbuf_evict_one ();
903
+ dbuf_evict ();
870
904
cv_signal (& dbuf_evict_cv );
871
905
}
872
906
}
@@ -4106,7 +4140,7 @@ dmu_buf_rele(dmu_buf_t *db, const void *tag)
4106
4140
* dbuf_rele()-->dbuf_rele_and_unlock()-->dbuf_evict_notify()
4107
4141
* ^ |
4108
4142
* | |
4109
- * +-----dbuf_destroy()<--dbuf_evict_one ()<--------+
4143
+ * +-----dbuf_destroy()<--dbuf_evict ()<--------+
4110
4144
*
4111
4145
*/
4112
4146
void
0 commit comments