Skip to content

Commit 31d8939

Browse files
Christoph Hellwigkdave
authored andcommitted
btrfs: remove the extent_buffer lookup in btree block checksumming
The checksumming of btree blocks always operates on the entire extent_buffer, and because btree blocks are always allocated contiguously on disk they are never split by btrfs_submit_bio. Simplify the checksumming code by finding the extent_buffer in the btrfs_bio private data instead of trying to search through the bio_vec. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent cd88a4f commit 31d8939

File tree

1 file changed

+24
-96
lines changed

1 file changed

+24
-96
lines changed

fs/btrfs/disk-io.c

Lines changed: 24 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -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

292313
error:
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

Comments
 (0)