@@ -503,6 +503,98 @@ xfs_buf_hash_destroy(
503503 rhashtable_destroy (& pag -> pag_buf_hash );
504504}
505505
506+ static int
507+ xfs_buf_map_verify (
508+ struct xfs_buftarg * btp ,
509+ struct xfs_buf_map * map )
510+ {
511+ xfs_daddr_t eofs ;
512+
513+ /* Check for IOs smaller than the sector size / not sector aligned */
514+ ASSERT (!(BBTOB (map -> bm_len ) < btp -> bt_meta_sectorsize ));
515+ ASSERT (!(BBTOB (map -> bm_bn ) & (xfs_off_t )btp -> bt_meta_sectormask ));
516+
517+ /*
518+ * Corrupted block numbers can get through to here, unfortunately, so we
519+ * have to check that the buffer falls within the filesystem bounds.
520+ */
521+ eofs = XFS_FSB_TO_BB (btp -> bt_mount , btp -> bt_mount -> m_sb .sb_dblocks );
522+ if (map -> bm_bn < 0 || map -> bm_bn >= eofs ) {
523+ xfs_alert (btp -> bt_mount ,
524+ "%s: daddr 0x%llx out of range, EOFS 0x%llx" ,
525+ __func__ , map -> bm_bn , eofs );
526+ WARN_ON (1 );
527+ return - EFSCORRUPTED ;
528+ }
529+ return 0 ;
530+ }
531+
532+ static int
533+ xfs_buf_find_lock (
534+ struct xfs_buf * bp ,
535+ xfs_buf_flags_t flags )
536+ {
537+ if (!xfs_buf_trylock (bp )) {
538+ if (flags & XBF_TRYLOCK ) {
539+ XFS_STATS_INC (bp -> b_mount , xb_busy_locked );
540+ xfs_buf_rele (bp );
541+ return - EAGAIN ;
542+ }
543+ xfs_buf_lock (bp );
544+ XFS_STATS_INC (bp -> b_mount , xb_get_locked_waited );
545+ }
546+
547+ /*
548+ * if the buffer is stale, clear all the external state associated with
549+ * it. We need to keep flags such as how we allocated the buffer memory
550+ * intact here.
551+ */
552+ if (bp -> b_flags & XBF_STALE ) {
553+ ASSERT ((bp -> b_flags & _XBF_DELWRI_Q ) == 0 );
554+ bp -> b_flags &= _XBF_KMEM | _XBF_PAGES ;
555+ bp -> b_ops = NULL ;
556+ }
557+ return 0 ;
558+ }
559+
560+ static inline struct xfs_buf *
561+ xfs_buf_lookup (
562+ struct xfs_perag * pag ,
563+ struct xfs_buf_map * map )
564+ {
565+ struct xfs_buf * bp ;
566+
567+ bp = rhashtable_lookup (& pag -> pag_buf_hash , map , xfs_buf_hash_params );
568+ if (!bp )
569+ return NULL ;
570+ atomic_inc (& bp -> b_hold );
571+ return bp ;
572+ }
573+
574+ /*
575+ * Insert the new_bp into the hash table. This consumes the perag reference
576+ * taken for the lookup.
577+ */
578+ static int
579+ xfs_buf_find_insert (
580+ struct xfs_buftarg * btp ,
581+ struct xfs_perag * pag ,
582+ struct xfs_buf * new_bp )
583+ {
584+ /* No match found */
585+ if (!new_bp ) {
586+ xfs_perag_put (pag );
587+ XFS_STATS_INC (btp -> bt_mount , xb_miss_locked );
588+ return - ENOENT ;
589+ }
590+
591+ /* the buffer keeps the perag reference until it is freed */
592+ new_bp -> b_pag = pag ;
593+ rhashtable_insert_fast (& pag -> pag_buf_hash , & new_bp -> b_rhash_head ,
594+ xfs_buf_hash_params );
595+ return 0 ;
596+ }
597+
506598/*
507599 * Look up a buffer in the buffer cache and return it referenced and locked
508600 * in @found_bp.
@@ -533,82 +625,40 @@ xfs_buf_find(
533625 struct xfs_perag * pag ;
534626 struct xfs_buf * bp ;
535627 struct xfs_buf_map cmap = { .bm_bn = map [0 ].bm_bn };
536- xfs_daddr_t eofs ;
628+ int error ;
537629 int i ;
538630
539631 * found_bp = NULL ;
540632
541633 for (i = 0 ; i < nmaps ; i ++ )
542634 cmap .bm_len += map [i ].bm_len ;
543635
544- /* Check for IOs smaller than the sector size / not sector aligned */
545- ASSERT (!(BBTOB (cmap .bm_len ) < btp -> bt_meta_sectorsize ));
546- ASSERT (!(BBTOB (cmap .bm_bn ) & (xfs_off_t )btp -> bt_meta_sectormask ));
547-
548- /*
549- * Corrupted block numbers can get through to here, unfortunately, so we
550- * have to check that the buffer falls within the filesystem bounds.
551- */
552- eofs = XFS_FSB_TO_BB (btp -> bt_mount , btp -> bt_mount -> m_sb .sb_dblocks );
553- if (cmap .bm_bn < 0 || cmap .bm_bn >= eofs ) {
554- xfs_alert (btp -> bt_mount ,
555- "%s: daddr 0x%llx out of range, EOFS 0x%llx" ,
556- __func__ , cmap .bm_bn , eofs );
557- WARN_ON (1 );
558- return - EFSCORRUPTED ;
559- }
636+ error = xfs_buf_map_verify (btp , & cmap );
637+ if (error )
638+ return error ;
560639
561640 pag = xfs_perag_get (btp -> bt_mount ,
562641 xfs_daddr_to_agno (btp -> bt_mount , cmap .bm_bn ));
563642
564643 spin_lock (& pag -> pag_buf_lock );
565- bp = rhashtable_lookup_fast (& pag -> pag_buf_hash , & cmap ,
566- xfs_buf_hash_params );
567- if (bp ) {
568- atomic_inc (& bp -> b_hold );
644+ bp = xfs_buf_lookup (pag , & cmap );
645+ if (bp )
569646 goto found ;
570- }
571-
572- /* No match found */
573- if (!new_bp ) {
574- XFS_STATS_INC (btp -> bt_mount , xb_miss_locked );
575- spin_unlock (& pag -> pag_buf_lock );
576- xfs_perag_put (pag );
577- return - ENOENT ;
578- }
579647
580- /* the buffer keeps the perag reference until it is freed */
581- new_bp -> b_pag = pag ;
582- rhashtable_insert_fast (& pag -> pag_buf_hash , & new_bp -> b_rhash_head ,
583- xfs_buf_hash_params );
648+ error = xfs_buf_find_insert (btp , pag , new_bp );
584649 spin_unlock (& pag -> pag_buf_lock );
650+ if (error )
651+ return error ;
585652 * found_bp = new_bp ;
586653 return 0 ;
587654
588655found :
589656 spin_unlock (& pag -> pag_buf_lock );
590657 xfs_perag_put (pag );
591658
592- if (!xfs_buf_trylock (bp )) {
593- if (flags & XBF_TRYLOCK ) {
594- xfs_buf_rele (bp );
595- XFS_STATS_INC (btp -> bt_mount , xb_busy_locked );
596- return - EAGAIN ;
597- }
598- xfs_buf_lock (bp );
599- XFS_STATS_INC (btp -> bt_mount , xb_get_locked_waited );
600- }
601-
602- /*
603- * if the buffer is stale, clear all the external state associated with
604- * it. We need to keep flags such as how we allocated the buffer memory
605- * intact here.
606- */
607- if (bp -> b_flags & XBF_STALE ) {
608- ASSERT ((bp -> b_flags & _XBF_DELWRI_Q ) == 0 );
609- bp -> b_flags &= _XBF_KMEM | _XBF_PAGES ;
610- bp -> b_ops = NULL ;
611- }
659+ error = xfs_buf_find_lock (bp , flags );
660+ if (error )
661+ return error ;
612662
613663 trace_xfs_buf_find (bp , flags , _RET_IP_ );
614664 XFS_STATS_INC (btp -> bt_mount , xb_get_locked );
0 commit comments