From cfd59f904b0760f1bc909bc1b6deae9798042af9 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 18 Aug 2020 22:11:34 -0700 Subject: [PATCH] Fix ARC aggsum access after arc_state_fini() Commit 85ec5cbae updated abd_update_scatter_stats() such that it calls arc_space_consume() and arc_space_return() when updating the scatter stats. This requires that the global aggsum value for the ARC be initialized. Normally this is not an issue, however during module unload the l2arc_do_free_on_write() function was called in l2arc_cleanup() after arc_state_fini() destroyed the aggsum values. We can resolve this issue by performing l2arc_do_free_on_write() slightly earlier in arc_fini(). Reviewed-by: Matthew Ahrens Signed-off-by: Brian Behlendorf Closes #10739 --- module/zfs/arc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/zfs/arc.c b/module/zfs/arc.c index f63f92b86..0512497d5 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -886,6 +886,7 @@ static inline void arc_hdr_clear_flags(arc_buf_hdr_t *hdr, arc_flags_t flags); static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *); static void l2arc_read_done(zio_t *); +static void l2arc_do_free_on_write(void); /* * L2ARC TRIM @@ -7554,6 +7555,13 @@ arc_fini(void) mutex_destroy(&arc_evict_lock); list_destroy(&arc_evict_waiters); + /* + * Free any buffers that were tagged for destruction. This needs + * to occur before arc_state_fini() runs and destroys the aggsum + * values which are updated when freeing scatter ABDs. + */ + l2arc_do_free_on_write(); + /* * buf_fini() must proceed arc_state_fini() because buf_fin() may * trigger the release of kmem magazines, which can callback to @@ -9451,14 +9459,6 @@ l2arc_init(void) void l2arc_fini(void) { - /* - * This is called from dmu_fini(), which is called from spa_fini(); - * Because of this, we can assume that all l2arc devices have - * already been removed when the pools themselves were removed. - */ - - l2arc_do_free_on_write(); - mutex_destroy(&l2arc_feed_thr_lock); cv_destroy(&l2arc_feed_thr_cv); mutex_destroy(&l2arc_rebuild_thr_lock);