@@ -472,6 +472,7 @@ xfs_buf_find_insert(
472472 /* The new buffer keeps the perag reference until it is freed. */
473473 new_bp -> b_pag = pag ;
474474
475+ retry :
475476 rcu_read_lock ();
476477 bp = rhashtable_lookup_get_insert_fast (& btp -> bt_hash ,
477478 & new_bp -> b_rhash_head , xfs_buf_hash_params );
@@ -480,8 +481,16 @@ xfs_buf_find_insert(
480481 error = PTR_ERR (bp );
481482 goto out_free_buf ;
482483 }
483- if (bp && lockref_get_not_dead (& bp -> b_lockref )) {
484- /* found an existing buffer */
484+ if (bp ) {
485+ /*
486+ * If there is an existing buffer with a dead lockref, retry
487+ * until the new buffer is added, or a usable buffer is found.
488+ */
489+ if (!lockref_get_not_dead (& bp -> b_lockref )) {
490+ rcu_read_unlock ();
491+ cpu_relax ();
492+ goto retry ;
493+ }
485494 rcu_read_unlock ();
486495 error = xfs_buf_find_lock (bp , flags );
487496 if (error )
@@ -820,15 +829,20 @@ xfs_buf_destroy(
820829 ASSERT (__lockref_is_dead (& bp -> b_lockref ));
821830 ASSERT (!(bp -> b_flags & _XBF_DELWRI_Q ));
822831
832+ if (bp -> b_pag )
833+ xfs_perag_put (bp -> b_pag );
834+ xfs_buf_free (bp );
835+ }
836+
837+ static inline void
838+ xfs_buf_kill (
839+ struct xfs_buf * bp )
840+ {
841+ lockref_mark_dead (& bp -> b_lockref );
823842 if (!xfs_buf_is_uncached (bp )) {
824843 rhashtable_remove_fast (& bp -> b_target -> bt_hash ,
825844 & bp -> b_rhash_head , xfs_buf_hash_params );
826-
827- if (bp -> b_pag )
828- xfs_perag_put (bp -> b_pag );
829845 }
830-
831- xfs_buf_free (bp );
832846}
833847
834848/*
@@ -851,7 +865,7 @@ xfs_buf_rele(
851865 return ;
852866
853867kill :
854- lockref_mark_dead ( & bp -> b_lockref );
868+ xfs_buf_kill ( bp );
855869 list_lru_del_obj (& bp -> b_target -> bt_lru , & bp -> b_lru );
856870 spin_unlock (& bp -> b_lockref .lock );
857871
@@ -1433,7 +1447,7 @@ xfs_buftarg_drain_rele(
14331447 return LRU_SKIP ;
14341448 }
14351449
1436- lockref_mark_dead ( & bp -> b_lockref );
1450+ xfs_buf_kill ( bp );
14371451 list_lru_isolate_move (lru , item , dispose );
14381452 spin_unlock (& bp -> b_lockref .lock );
14391453 return LRU_REMOVED ;
@@ -1545,7 +1559,7 @@ xfs_buftarg_isolate(
15451559 return LRU_ROTATE ;
15461560 }
15471561
1548- lockref_mark_dead ( & bp -> b_lockref );
1562+ xfs_buf_kill ( bp );
15491563 list_lru_isolate_move (lru , item , dispose );
15501564 spin_unlock (& bp -> b_lockref .lock );
15511565 return LRU_REMOVED ;
0 commit comments