@@ -254,12 +254,34 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb,
254254 return ret ;
255255}
256256
257- static int csum_one_extent_buffer (struct extent_buffer * eb )
257+ /*
258+ * Checksum a dirty tree block before IO.
259+ */
260+ blk_status_t btree_csum_one_bio (struct btrfs_bio * bbio )
258261{
262+ struct extent_buffer * eb = bbio -> private ;
259263 struct btrfs_fs_info * fs_info = eb -> fs_info ;
264+ u64 found_start = btrfs_header_bytenr (eb );
260265 u8 result [BTRFS_CSUM_SIZE ];
261266 int ret ;
262267
268+ /* Btree blocks are always contiguous on disk. */
269+ if (WARN_ON_ONCE (bbio -> file_offset != eb -> start ))
270+ return BLK_STS_IOERR ;
271+ if (WARN_ON_ONCE (bbio -> bio .bi_iter .bi_size != eb -> len ))
272+ return BLK_STS_IOERR ;
273+
274+ if (test_bit (EXTENT_BUFFER_NO_CHECK , & eb -> bflags )) {
275+ WARN_ON_ONCE (found_start != 0 );
276+ return BLK_STS_OK ;
277+ }
278+
279+ if (WARN_ON_ONCE (found_start != eb -> start ))
280+ return BLK_STS_IOERR ;
281+ if (WARN_ON (!btrfs_page_test_uptodate (fs_info , eb -> pages [0 ], eb -> start ,
282+ eb -> len )))
283+ return BLK_STS_IOERR ;
284+
263285 ASSERT (memcmp_extent_buffer (eb , fs_info -> fs_devices -> metadata_uuid ,
264286 offsetof(struct btrfs_header , fsid ),
265287 BTRFS_FSID_SIZE ) == 0 );
@@ -286,8 +308,7 @@ static int csum_one_extent_buffer(struct extent_buffer *eb)
286308 goto error ;
287309 }
288310 write_extent_buffer (eb , result , 0 , fs_info -> csum_size );
289-
290- return 0 ;
311+ return BLK_STS_OK ;
291312
292313error :
293314 btrfs_print_tree (eb , 0 );
@@ -301,99 +322,6 @@ static int csum_one_extent_buffer(struct extent_buffer *eb)
301322 */
302323 WARN_ON (IS_ENABLED (CONFIG_BTRFS_DEBUG ) ||
303324 btrfs_header_owner (eb ) == BTRFS_TREE_LOG_OBJECTID );
304- return ret ;
305- }
306-
307- /* Checksum all dirty extent buffers in one bio_vec */
308- static int csum_dirty_subpage_buffers (struct btrfs_fs_info * fs_info ,
309- struct bio_vec * bvec )
310- {
311- struct page * page = bvec -> bv_page ;
312- u64 bvec_start = page_offset (page ) + bvec -> bv_offset ;
313- u64 cur ;
314- int ret = 0 ;
315-
316- for (cur = bvec_start ; cur < bvec_start + bvec -> bv_len ;
317- cur += fs_info -> nodesize ) {
318- struct extent_buffer * eb ;
319- bool uptodate ;
320-
321- eb = find_extent_buffer (fs_info , cur );
322- uptodate = btrfs_subpage_test_uptodate (fs_info , page , cur ,
323- fs_info -> nodesize );
324-
325- /* A dirty eb shouldn't disappear from buffer_radix */
326- if (WARN_ON (!eb ))
327- return - EUCLEAN ;
328-
329- if (WARN_ON (cur != btrfs_header_bytenr (eb ))) {
330- free_extent_buffer (eb );
331- return - EUCLEAN ;
332- }
333- if (WARN_ON (!uptodate )) {
334- free_extent_buffer (eb );
335- return - EUCLEAN ;
336- }
337-
338- ret = csum_one_extent_buffer (eb );
339- free_extent_buffer (eb );
340- if (ret < 0 )
341- return ret ;
342- }
343- return ret ;
344- }
345-
346- /*
347- * Checksum a dirty tree block before IO. This has extra checks to make sure
348- * we only fill in the checksum field in the first page of a multi-page block.
349- * For subpage extent buffers we need bvec to also read the offset in the page.
350- */
351- static int csum_dirty_buffer (struct btrfs_fs_info * fs_info , struct bio_vec * bvec )
352- {
353- struct page * page = bvec -> bv_page ;
354- u64 start = page_offset (page );
355- u64 found_start ;
356- struct extent_buffer * eb ;
357-
358- if (fs_info -> nodesize < PAGE_SIZE )
359- return csum_dirty_subpage_buffers (fs_info , bvec );
360-
361- eb = (struct extent_buffer * )page -> private ;
362- if (page != eb -> pages [0 ])
363- return 0 ;
364-
365- found_start = btrfs_header_bytenr (eb );
366-
367- if (test_bit (EXTENT_BUFFER_NO_CHECK , & eb -> bflags )) {
368- WARN_ON (found_start != 0 );
369- return 0 ;
370- }
371-
372- /*
373- * Please do not consolidate these warnings into a single if.
374- * It is useful to know what went wrong.
375- */
376- if (WARN_ON (found_start != start ))
377- return - EUCLEAN ;
378- if (WARN_ON (!PageUptodate (page )))
379- return - EUCLEAN ;
380-
381- return csum_one_extent_buffer (eb );
382- }
383-
384- blk_status_t btree_csum_one_bio (struct btrfs_bio * bbio )
385- {
386- struct btrfs_fs_info * fs_info = bbio -> inode -> root -> fs_info ;
387- struct bvec_iter iter ;
388- struct bio_vec bv ;
389- int ret = 0 ;
390-
391- bio_for_each_segment (bv , & bbio -> bio , iter ) {
392- ret = csum_dirty_buffer (fs_info , & bv );
393- if (ret )
394- break ;
395- }
396-
397325 return errno_to_blk_status (ret );
398326}
399327
0 commit comments