Skip to content

Commit 9150724

Browse files
adam900710kdave
authored andcommitted
btrfs: determine stripe boundary at bio allocation time in btrfs_submit_compressed_write
Currently btrfs_submit_compressed_write() will check btrfs_bio_fits_in_stripe() each time a new page is going to be added. Even if compressed extent is small, we don't really need to do that for every page. Align the behavior to extent_io.c, by determining the stripe boundary when allocating a bio. Unlike extent_io.c, in compressed.c we don't need to bother things like different bio flags, thus no need to re-use bio_ctrl. Here we just manually introduce new local variable, next_stripe_start, and use that value returned from alloc_compressed_bio() to calculate the stripe boundary. Then each time we add some page range into the bio, we check if we reached the boundary. And if reached, submit it. Also, since we have @cur_disk_bytenr to determine whether we're the last bio, we don't need a explicit last_bio: tag for error handling any more. And since we use @cur_disk_bytenr to wait, there is no need for pending_bios, also remove it to save some memory of compressed_bio. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent f472c28 commit 9150724

File tree

2 files changed

+59
-85
lines changed

2 files changed

+59
-85
lines changed

fs/btrfs/compression.c

Lines changed: 59 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ static bool dec_and_test_compressed_bio(struct compressed_bio *cb, struct bio *b
221221
ASSERT(bi_size && bi_size <= cb->compressed_len);
222222
last_io = refcount_sub_and_test(bi_size >> fs_info->sectorsize_bits,
223223
&cb->pending_sectors);
224-
atomic_dec(&cb->pending_bios);
225224
/*
226225
* Here we must wake up the possible error handler after all other
227226
* operations on @cb finished, or we can race with
@@ -426,7 +425,6 @@ static blk_status_t submit_compressed_bio(struct btrfs_fs_info *fs_info,
426425
blk_status_t ret;
427426

428427
ASSERT(bio->bi_iter.bi_size);
429-
atomic_inc(&cb->pending_bios);
430428
ret = btrfs_bio_wq_end_io(fs_info, bio, BTRFS_WQ_ENDIO_DATA);
431429
if (ret)
432430
return ret;
@@ -508,10 +506,7 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
508506
struct btrfs_fs_info *fs_info = inode->root->fs_info;
509507
struct bio *bio = NULL;
510508
struct compressed_bio *cb;
511-
unsigned long bytes_left;
512-
int pg_index = 0;
513-
struct page *page;
514-
u64 first_byte = disk_start;
509+
u64 cur_disk_bytenr = disk_start;
515510
u64 next_stripe_start;
516511
blk_status_t ret;
517512
int skip_sum = inode->flags & BTRFS_INODE_NODATASUM;
@@ -522,7 +517,6 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
522517
cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
523518
if (!cb)
524519
return BLK_STS_RESOURCE;
525-
atomic_set(&cb->pending_bios, 0);
526520
refcount_set(&cb->pending_sectors, compressed_len >> fs_info->sectorsize_bits);
527521
cb->errors = 0;
528522
cb->inode = &inode->vfs_inode;
@@ -534,44 +528,62 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
534528
cb->orig_bio = NULL;
535529
cb->nr_pages = nr_pages;
536530

537-
bio = alloc_compressed_bio(cb, first_byte, bio_op | write_flags,
538-
end_compressed_bio_write, &next_stripe_start);
539-
if (IS_ERR(bio)) {
540-
kfree(cb);
541-
return errno_to_blk_status(PTR_ERR(bio));
542-
}
543-
544-
if (blkcg_css) {
545-
bio->bi_opf |= REQ_CGROUP_PUNT;
546-
kthread_associate_blkcg(blkcg_css);
547-
}
548-
549-
/* create and submit bios for the compressed pages */
550-
bytes_left = compressed_len;
551-
for (pg_index = 0; pg_index < cb->nr_pages; pg_index++) {
552-
int submit = 0;
553-
int len = 0;
531+
while (cur_disk_bytenr < disk_start + compressed_len) {
532+
u64 offset = cur_disk_bytenr - disk_start;
533+
unsigned int index = offset >> PAGE_SHIFT;
534+
unsigned int real_size;
535+
unsigned int added;
536+
struct page *page = compressed_pages[index];
537+
bool submit = false;
554538

555-
page = compressed_pages[pg_index];
556-
page->mapping = inode->vfs_inode.i_mapping;
557-
if (bio->bi_iter.bi_size)
558-
submit = btrfs_bio_fits_in_stripe(page, PAGE_SIZE, bio,
559-
0);
539+
/* Allocate new bio if submitted or not yet allocated */
540+
if (!bio) {
541+
bio = alloc_compressed_bio(cb, cur_disk_bytenr,
542+
bio_op | write_flags, end_compressed_bio_write,
543+
&next_stripe_start);
544+
if (IS_ERR(bio)) {
545+
ret = errno_to_blk_status(PTR_ERR(bio));
546+
bio = NULL;
547+
goto finish_cb;
548+
}
549+
}
550+
/*
551+
* We should never reach next_stripe_start start as we will
552+
* submit comp_bio when reach the boundary immediately.
553+
*/
554+
ASSERT(cur_disk_bytenr != next_stripe_start);
560555

561556
/*
562-
* Page can only be added to bio if the current bio fits in
563-
* stripe.
557+
* We have various limits on the real read size:
558+
* - stripe boundary
559+
* - page boundary
560+
* - compressed length boundary
564561
*/
565-
if (!submit) {
566-
if (pg_index == 0 && use_append)
567-
len = bio_add_zone_append_page(bio, page,
568-
PAGE_SIZE, 0);
569-
else
570-
len = bio_add_page(bio, page, PAGE_SIZE, 0);
571-
}
562+
real_size = min_t(u64, U32_MAX, next_stripe_start - cur_disk_bytenr);
563+
real_size = min_t(u64, real_size, PAGE_SIZE - offset_in_page(offset));
564+
real_size = min_t(u64, real_size, compressed_len - offset);
565+
ASSERT(IS_ALIGNED(real_size, fs_info->sectorsize));
572566

573-
page->mapping = NULL;
574-
if (submit || len < PAGE_SIZE) {
567+
if (use_append)
568+
added = bio_add_zone_append_page(bio, page, real_size,
569+
offset_in_page(offset));
570+
else
571+
added = bio_add_page(bio, page, real_size,
572+
offset_in_page(offset));
573+
/* Reached zoned boundary */
574+
if (added == 0)
575+
submit = true;
576+
577+
cur_disk_bytenr += added;
578+
/* Reached stripe boundary */
579+
if (cur_disk_bytenr == next_stripe_start)
580+
submit = true;
581+
582+
/* Finished the range */
583+
if (cur_disk_bytenr == disk_start + compressed_len)
584+
submit = true;
585+
586+
if (submit) {
575587
if (!skip_sum) {
576588
ret = btrfs_csum_one_bio(inode, bio, start, 1);
577589
if (ret)
@@ -581,61 +593,27 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
581593
ret = submit_compressed_bio(fs_info, cb, bio, 0);
582594
if (ret)
583595
goto finish_cb;
584-
585-
bio = alloc_compressed_bio(cb, first_byte,
586-
bio_op | write_flags,
587-
end_compressed_bio_write,
588-
&next_stripe_start);
589-
if (IS_ERR(bio)) {
590-
ret = errno_to_blk_status(PTR_ERR(bio));
591-
bio = NULL;
592-
goto finish_cb;
593-
}
594-
if (blkcg_css)
595-
bio->bi_opf |= REQ_CGROUP_PUNT;
596-
/*
597-
* Use bio_add_page() to ensure the bio has at least one
598-
* page.
599-
*/
600-
bio_add_page(bio, page, PAGE_SIZE, 0);
596+
bio = NULL;
601597
}
602-
if (bytes_left < PAGE_SIZE) {
603-
btrfs_info(fs_info,
604-
"bytes left %lu compress len %u nr %u",
605-
bytes_left, cb->compressed_len, cb->nr_pages);
606-
}
607-
bytes_left -= PAGE_SIZE;
608-
first_byte += PAGE_SIZE;
609598
cond_resched();
610599
}
611-
612-
if (!skip_sum) {
613-
ret = btrfs_csum_one_bio(inode, bio, start, 1);
614-
if (ret)
615-
goto last_bio;
616-
}
617-
618-
ret = submit_compressed_bio(fs_info, cb, bio, 0);
619-
if (ret)
620-
goto last_bio;
621-
622600
if (blkcg_css)
623601
kthread_associate_blkcg(NULL);
624602

625603
return 0;
626-
last_bio:
627-
bio->bi_status = ret;
628-
/* One of the bios' endio function will free @cb. */
629-
bio_endio(bio);
630-
return ret;
631604

632605
finish_cb:
633606
if (bio) {
634607
bio->bi_status = ret;
635608
bio_endio(bio);
636609
}
610+
/* Last byte of @cb is submitted, endio will free @cb */
611+
if (cur_disk_bytenr == disk_start + compressed_len)
612+
return ret;
637613

638-
wait_var_event(cb, atomic_read(&cb->pending_bios) == 0);
614+
wait_var_event(cb, refcount_read(&cb->pending_sectors) ==
615+
(disk_start + compressed_len - cur_disk_bytenr) >>
616+
fs_info->sectorsize_bits);
639617
/*
640618
* Even with previous bio ended, we should still have io not yet
641619
* submitted, thus need to finish manually.
@@ -846,7 +824,6 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
846824
if (!cb)
847825
goto out;
848826

849-
atomic_set(&cb->pending_bios, 0);
850827
refcount_set(&cb->pending_sectors, compressed_len >> fs_info->sectorsize_bits);
851828
cb->errors = 0;
852829
cb->inode = inode;

fs/btrfs/compression.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ struct btrfs_inode;
2828
#define BTRFS_ZLIB_DEFAULT_LEVEL 3
2929

3030
struct compressed_bio {
31-
/* Number of bios pending for this compressed extent */
32-
atomic_t pending_bios;
33-
3431
/* Number of sectors with unfinished IO (unsubmitted or unfinished) */
3532
refcount_t pending_sectors;
3633

0 commit comments

Comments
 (0)