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 <mahrens@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #10739
This commit is contained in:
Brian Behlendorf 2020-08-18 22:11:34 -07:00 committed by GitHub
parent 4f7fb135bd
commit cfd59f904b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 8 additions and 8 deletions

View File

@ -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 boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *);
static void l2arc_read_done(zio_t *); static void l2arc_read_done(zio_t *);
static void l2arc_do_free_on_write(void);
/* /*
* L2ARC TRIM * L2ARC TRIM
@ -7554,6 +7555,13 @@ arc_fini(void)
mutex_destroy(&arc_evict_lock); mutex_destroy(&arc_evict_lock);
list_destroy(&arc_evict_waiters); 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 * buf_fini() must proceed arc_state_fini() because buf_fin() may
* trigger the release of kmem magazines, which can callback to * trigger the release of kmem magazines, which can callback to
@ -9451,14 +9459,6 @@ l2arc_init(void)
void void
l2arc_fini(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); mutex_destroy(&l2arc_feed_thr_lock);
cv_destroy(&l2arc_feed_thr_cv); cv_destroy(&l2arc_feed_thr_cv);
mutex_destroy(&l2arc_rebuild_thr_lock); mutex_destroy(&l2arc_rebuild_thr_lock);