@@ -9073,6 +9073,8 @@ l2arc_pool_markers_init(spa_t *spa)
90739073 arc_state_alloc_markers (num_sublists );
90749074 spa -> spa_l2arc_info .l2arc_sublist_busy [pass ] =
90759075 kmem_zalloc (num_sublists * sizeof (boolean_t ), KM_SLEEP );
9076+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ] =
9077+ kmem_zalloc (num_sublists * sizeof (boolean_t ), KM_SLEEP );
90769078
90779079 for (int i = 0 ; i < num_sublists ; i ++ ) {
90789080 multilist_sublist_t * mls =
@@ -9117,12 +9119,18 @@ l2arc_pool_markers_fini(spa_t *spa)
91179119 num_sublists );
91189120 spa -> spa_l2arc_info .l2arc_markers [pass ] = NULL ;
91199121
9120- /* Free sublist busy flags for this pass */
9122+ /* Free sublist busy and reset flags for this pass */
91219123 ASSERT3P (spa -> spa_l2arc_info .l2arc_sublist_busy [pass ], != ,
91229124 NULL );
91239125 kmem_free (spa -> spa_l2arc_info .l2arc_sublist_busy [pass ],
91249126 num_sublists * sizeof (boolean_t ));
91259127 spa -> spa_l2arc_info .l2arc_sublist_busy [pass ] = NULL ;
9128+
9129+ ASSERT3P (spa -> spa_l2arc_info .l2arc_sublist_reset [pass ], != ,
9130+ NULL );
9131+ kmem_free (spa -> spa_l2arc_info .l2arc_sublist_reset [pass ],
9132+ num_sublists * sizeof (boolean_t ));
9133+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ] = NULL ;
91269134 }
91279135
91289136 mutex_destroy (& spa -> spa_l2arc_info .l2arc_sublist_lock );
@@ -9608,6 +9616,19 @@ l2arc_write_sublist(spa_t *spa, l2arc_dev_t *dev, int pass, int sublist_idx,
96089616 persistent_marker = spa -> spa_l2arc_info .
96099617 l2arc_markers [pass ][sublist_idx ];
96109618
9619+ /*
9620+ * Check if this sublist's marker was flagged for reset to tail.
9621+ * This handles depth cap resets and global resets without needing
9622+ * to coordinate with actively-scanning threads.
9623+ */
9624+ if (save_position &&
9625+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ][sublist_idx ]) {
9626+ multilist_sublist_remove (mls , persistent_marker );
9627+ multilist_sublist_insert_tail (mls , persistent_marker );
9628+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ][sublist_idx ] =
9629+ B_FALSE ;
9630+ }
9631+
96119632 if (save_position && persistent_marker == multilist_sublist_head (mls )) {
96129633 multilist_sublist_unlock (mls );
96139634 return (B_FALSE );
@@ -9798,14 +9819,24 @@ l2arc_write_sublist(spa_t *spa, l2arc_dev_t *dev, int pass, int sublist_idx,
97989819 }
97999820
98009821 /*
9801- * Position persistent marker for next iteration. In case of
9802- * save_position, validate that prev_hdr still belongs to the current
9803- * sublist. The sublist lock is dropped during L2ARC write I/O, allowing
9804- * ARC eviction to potentially free prev_hdr. If freed, we can't do much
9805- * except to reset the marker.
9822+ * Position persistent marker for next iteration.
9823+ *
9824+ * If a reset was flagged during our scan (sublist lock was dropped
9825+ * for I/O, allowing another thread to set the flag), honor it by
9826+ * moving the marker to tail instead of advancing.
9827+ *
9828+ * Otherwise, validate that prev_hdr still belongs to the current
9829+ * sublist. The sublist lock is dropped during L2ARC write I/O,
9830+ * allowing ARC eviction to potentially free prev_hdr. If freed,
9831+ * we can't do much except to reset the marker.
98069832 */
98079833 multilist_sublist_remove (mls , persistent_marker );
98089834 if (save_position &&
9835+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ][sublist_idx ]) {
9836+ multilist_sublist_insert_tail (mls , persistent_marker );
9837+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ][sublist_idx ] =
9838+ B_FALSE ;
9839+ } else if (save_position &&
98099840 multilist_link_active (& prev_hdr -> b_l1hdr .b_arc_node )) {
98109841 if (hdr != NULL ) {
98119842 /*
@@ -9845,40 +9876,33 @@ l2arc_blk_fetch_done(zio_t *zio)
98459876}
98469877
98479878/*
9848- * Reset all L2ARC markers to tail position for the given spa.
9879+ * Flag all sublists for a single pass for lazy marker reset to tail.
9880+ * Each sublist's marker will be reset when next visited by a feed thread.
98499881 */
98509882static void
9851- l2arc_reset_all_markers (spa_t * spa )
9883+ l2arc_flag_pass_reset (spa_t * spa , int pass )
98529884{
9853- ASSERT (spa -> spa_l2arc_info .l2arc_markers != NULL );
98549885 ASSERT (MUTEX_HELD (& spa -> spa_l2arc_info .l2arc_sublist_lock ));
98559886
9856- for (int pass = 0 ; pass < L2ARC_FEED_TYPES ; pass ++ ) {
9857- if (spa -> spa_l2arc_info .l2arc_markers [pass ] == NULL )
9858- continue ;
9859-
9860- multilist_t * ml = l2arc_get_list (pass );
9861- int num_sublists = multilist_get_num_sublists (ml );
9862-
9863- for (int i = 0 ; i < num_sublists ; i ++ ) {
9864- ASSERT3P (spa -> spa_l2arc_info .l2arc_markers [pass ][i ],
9865- != , NULL );
9866- multilist_sublist_t * mls =
9867- multilist_sublist_lock_idx (ml , i );
9868-
9869- /* Remove from current position */
9870- ASSERT (multilist_link_active (& spa -> spa_l2arc_info .
9871- l2arc_markers [pass ][i ]-> b_l1hdr .b_arc_node ));
9872- multilist_sublist_remove (mls , spa -> spa_l2arc_info .
9873- l2arc_markers [pass ][i ]);
9887+ multilist_t * ml = l2arc_get_list (pass );
9888+ int num_sublists = multilist_get_num_sublists (ml );
98749889
9875- /* Insert at tail (like initialization) */
9876- multilist_sublist_insert_tail (mls ,
9877- spa -> spa_l2arc_info .l2arc_markers [pass ][i ]);
9878-
9879- multilist_sublist_unlock (mls );
9880- }
9890+ for (int i = 0 ; i < num_sublists ; i ++ ) {
9891+ multilist_sublist_t * mls = multilist_sublist_lock_idx (ml , i );
9892+ spa -> spa_l2arc_info .l2arc_sublist_reset [pass ][i ] = B_TRUE ;
9893+ multilist_sublist_unlock (mls );
98819894 }
9895+ }
9896+
9897+ /*
9898+ * Flag all L2ARC markers for lazy reset to tail for the given spa.
9899+ * Each sublist's marker will be reset when next visited by a feed thread.
9900+ */
9901+ static void
9902+ l2arc_reset_all_markers (spa_t * spa )
9903+ {
9904+ for (int pass = 0 ; pass < L2ARC_FEED_TYPES ; pass ++ )
9905+ l2arc_flag_pass_reset (spa , pass );
98829906
98839907 /* Reset write counter */
98849908 spa -> spa_l2arc_info .l2arc_total_writes = 0 ;
0 commit comments