7070 *
7171 * The caller is responsible for locking the AG headers for the entire rebuild
7272 * operation so that nothing else can sneak in and change the AG state while
73- * we're not looking. We also assume that the caller already invalidated any
74- * buffers associated with @bitmap.
73+ * we're not looking. We must also invalidate any buffers associated with
74+ * @bitmap.
7575 */
7676
77- static int
78- xrep_invalidate_block (
79- uint64_t fsbno ,
80- void * priv )
81- {
82- struct xfs_scrub * sc = priv ;
83- struct xfs_buf * bp ;
84- int error ;
85-
86- /* Skip AG headers and post-EOFS blocks */
87- if (!xfs_verify_fsbno (sc -> mp , fsbno ))
88- return 0 ;
89-
90- error = xfs_buf_incore (sc -> mp -> m_ddev_targp ,
91- XFS_FSB_TO_DADDR (sc -> mp , fsbno ),
92- XFS_FSB_TO_BB (sc -> mp , 1 ), XBF_TRYLOCK , & bp );
93- if (error )
94- return 0 ;
95-
96- xfs_trans_bjoin (sc -> tp , bp );
97- xfs_trans_binval (sc -> tp , bp );
98- return 0 ;
99- }
100-
101- /*
102- * Invalidate buffers for per-AG btree blocks we're dumping. This function
103- * is not intended for use with file data repairs; we have bunmapi for that.
104- */
105- int
106- xrep_invalidate_blocks (
107- struct xfs_scrub * sc ,
108- struct xbitmap * bitmap )
109- {
110- /*
111- * For each block in each extent, see if there's an incore buffer for
112- * exactly that block; if so, invalidate it. The buffer cache only
113- * lets us look for one buffer at a time, so we have to look one block
114- * at a time. Avoid invalidating AG headers and post-EOFS blocks
115- * because we never own those; and if we can't TRYLOCK the buffer we
116- * assume it's owned by someone else.
117- */
118- return xbitmap_walk_bits (bitmap , xrep_invalidate_block , sc );
119- }
120-
12177/* Information about reaping extents after a repair. */
12278struct xrep_reap_state {
12379 struct xfs_scrub * sc ;
@@ -127,9 +83,7 @@ struct xrep_reap_state {
12783 enum xfs_ag_resv_type resv ;
12884};
12985
130- /*
131- * Put a block back on the AGFL.
132- */
86+ /* Put a block back on the AGFL. */
13387STATIC int
13488xrep_put_freelist (
13589 struct xfs_scrub * sc ,
@@ -168,6 +122,37 @@ xrep_put_freelist(
168122 return 0 ;
169123}
170124
125+ /* Try to invalidate the incore buffer for a block that we're about to free. */
126+ STATIC void
127+ xrep_block_reap_binval (
128+ struct xfs_scrub * sc ,
129+ xfs_fsblock_t fsbno )
130+ {
131+ struct xfs_buf * bp = NULL ;
132+ int error ;
133+
134+ /*
135+ * If there's an incore buffer for exactly this block, invalidate it.
136+ * Avoid invalidating AG headers and post-EOFS blocks because we never
137+ * own those.
138+ */
139+ if (!xfs_verify_fsbno (sc -> mp , fsbno ))
140+ return ;
141+
142+ /*
143+ * We assume that the lack of any other known owners means that the
144+ * buffer can be locked without risk of deadlocking.
145+ */
146+ error = xfs_buf_incore (sc -> mp -> m_ddev_targp ,
147+ XFS_FSB_TO_DADDR (sc -> mp , fsbno ),
148+ XFS_FSB_TO_BB (sc -> mp , 1 ), 0 , & bp );
149+ if (error )
150+ return ;
151+
152+ xfs_trans_bjoin (sc -> tp , bp );
153+ xfs_trans_binval (sc -> tp , bp );
154+ }
155+
171156/* Dispose of a single block. */
172157STATIC int
173158xrep_reap_block (
@@ -225,14 +210,17 @@ xrep_reap_block(
225210 * blow on writeout, the filesystem will shut down, and the admin gets
226211 * to run xfs_repair.
227212 */
228- if (has_other_rmap )
229- error = xfs_rmap_free (sc -> tp , agf_bp , sc -> sa .pag , agbno ,
230- 1 , rs -> oinfo );
231- else if (rs -> resv == XFS_AG_RESV_AGFL )
213+ if (has_other_rmap ) {
214+ error = xfs_rmap_free (sc -> tp , agf_bp , sc -> sa .pag , agbno , 1 ,
215+ rs -> oinfo );
216+ } else if (rs -> resv == XFS_AG_RESV_AGFL ) {
217+ xrep_block_reap_binval (sc , fsbno );
232218 error = xrep_put_freelist (sc , agbno );
233- else
219+ } else {
220+ xrep_block_reap_binval (sc , fsbno );
234221 error = xfs_free_extent (sc -> tp , sc -> sa .pag , agbno , 1 , rs -> oinfo ,
235222 rs -> resv );
223+ }
236224 if (agf_bp != sc -> sa .agf_bp )
237225 xfs_trans_brelse (sc -> tp , agf_bp );
238226 if (error )
0 commit comments