Commit da2f0f74 authored by Chris Mason's avatar Chris Mason

Btrfs: add support for blkio controllers

This attaches accounting information to bios as we submit them so the
new blkio controllers can throttle on btrfs filesystems.

Not much is required, we're just associating bios with blkcgs during clone,
calling wbc_init_bio()/wbc_account_io() during writepages submission,
and attaching the bios to the current context during direct IO.

Finally if we are splitting bios during btrfs_map_bio, this attaches
accounting information to the split.

The end result is able to throttle nicely on single disk filesystems.  A
little more work is required for multi-device filesystems.
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent a4027a20
...@@ -1724,6 +1724,7 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) ...@@ -1724,6 +1724,7 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE; bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE;
bdi->congested_fn = btrfs_congested_fn; bdi->congested_fn = btrfs_congested_fn;
bdi->congested_data = info; bdi->congested_data = info;
bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK;
return 0; return 0;
} }
......
...@@ -2730,6 +2730,9 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask) ...@@ -2730,6 +2730,9 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
btrfs_bio->csum = NULL; btrfs_bio->csum = NULL;
btrfs_bio->csum_allocated = NULL; btrfs_bio->csum_allocated = NULL;
btrfs_bio->end_io = NULL; btrfs_bio->end_io = NULL;
/* FIXME, put this into bio_clone_bioset */
if (bio->bi_css)
bio_associate_blkcg(new, bio->bi_css);
} }
return new; return new;
} }
...@@ -2790,6 +2793,7 @@ static int merge_bio(int rw, struct extent_io_tree *tree, struct page *page, ...@@ -2790,6 +2793,7 @@ static int merge_bio(int rw, struct extent_io_tree *tree, struct page *page,
} }
static int submit_extent_page(int rw, struct extent_io_tree *tree, static int submit_extent_page(int rw, struct extent_io_tree *tree,
struct writeback_control *wbc,
struct page *page, sector_t sector, struct page *page, sector_t sector,
size_t size, unsigned long offset, size_t size, unsigned long offset,
struct block_device *bdev, struct block_device *bdev,
...@@ -2826,6 +2830,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, ...@@ -2826,6 +2830,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
} }
bio = NULL; bio = NULL;
} else { } else {
if (wbc)
wbc_account_io(wbc, page, page_size);
return 0; return 0;
} }
} }
...@@ -2841,6 +2847,10 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, ...@@ -2841,6 +2847,10 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
bio_add_page(bio, page, page_size, offset); bio_add_page(bio, page, page_size, offset);
bio->bi_end_io = end_io_func; bio->bi_end_io = end_io_func;
bio->bi_private = tree; bio->bi_private = tree;
if (wbc) {
wbc_init_bio(wbc, bio);
wbc_account_io(wbc, page, page_size);
}
if (bio_ret) if (bio_ret)
*bio_ret = bio; *bio_ret = bio;
...@@ -3051,7 +3061,7 @@ static int __do_readpage(struct extent_io_tree *tree, ...@@ -3051,7 +3061,7 @@ static int __do_readpage(struct extent_io_tree *tree,
} }
pnr -= page->index; pnr -= page->index;
ret = submit_extent_page(rw, tree, page, ret = submit_extent_page(rw, tree, NULL, page,
sector, disk_io_size, pg_offset, sector, disk_io_size, pg_offset,
bdev, bio, pnr, bdev, bio, pnr,
end_bio_extent_readpage, mirror_num, end_bio_extent_readpage, mirror_num,
...@@ -3446,7 +3456,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, ...@@ -3446,7 +3456,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode,
page->index, cur, end); page->index, cur, end);
} }
ret = submit_extent_page(write_flags, tree, page, ret = submit_extent_page(write_flags, tree, wbc, page,
sector, iosize, pg_offset, sector, iosize, pg_offset,
bdev, &epd->bio, max_nr, bdev, &epd->bio, max_nr,
end_bio_extent_writepage, end_bio_extent_writepage,
...@@ -3749,7 +3759,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, ...@@ -3749,7 +3759,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
clear_page_dirty_for_io(p); clear_page_dirty_for_io(p);
set_page_writeback(p); set_page_writeback(p);
ret = submit_extent_page(rw, tree, p, offset >> 9, ret = submit_extent_page(rw, tree, wbc, p, offset >> 9,
PAGE_CACHE_SIZE, 0, bdev, &epd->bio, PAGE_CACHE_SIZE, 0, bdev, &epd->bio,
-1, end_bio_extent_buffer_writepage, -1, end_bio_extent_buffer_writepage,
0, epd->bio_flags, bio_flags); 0, epd->bio_flags, bio_flags);
......
...@@ -7987,7 +7987,11 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev, ...@@ -7987,7 +7987,11 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
u64 first_sector, gfp_t gfp_flags) u64 first_sector, gfp_t gfp_flags)
{ {
int nr_vecs = bio_get_nr_vecs(bdev); int nr_vecs = bio_get_nr_vecs(bdev);
return btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags); struct bio *bio;
bio = btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags);
if (bio)
bio_associate_current(bio);
return bio;
} }
static inline int btrfs_lookup_and_bind_dio_csum(struct btrfs_root *root, static inline int btrfs_lookup_and_bind_dio_csum(struct btrfs_root *root,
......
...@@ -1033,6 +1033,7 @@ static int btrfs_fill_super(struct super_block *sb, ...@@ -1033,6 +1033,7 @@ static int btrfs_fill_super(struct super_block *sb,
sb->s_flags |= MS_POSIXACL; sb->s_flags |= MS_POSIXACL;
#endif #endif
sb->s_flags |= MS_I_VERSION; sb->s_flags |= MS_I_VERSION;
sb->s_iflags |= SB_I_CGROUPWB;
err = open_ctree(sb, fs_devices, (char *)data); err = open_ctree(sb, fs_devices, (char *)data);
if (err) { if (err) {
printk(KERN_ERR "BTRFS: open_ctree failed\n"); printk(KERN_ERR "BTRFS: open_ctree failed\n");
......
...@@ -5942,6 +5942,14 @@ static int breakup_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio, ...@@ -5942,6 +5942,14 @@ static int breakup_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
if (!bio) if (!bio)
return -ENOMEM; return -ENOMEM;
if (first_bio->bi_ioc) {
get_io_context_active(first_bio->bi_ioc);
bio->bi_ioc = first_bio->bi_ioc;
}
if (first_bio->bi_css) {
css_get(first_bio->bi_css);
bio->bi_css = first_bio->bi_css;
}
while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) { while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) {
if (bio_add_page(bio, bvec->bv_page, bvec->bv_len, if (bio_add_page(bio, bvec->bv_page, bvec->bv_len,
bvec->bv_offset) < bvec->bv_len) { bvec->bv_offset) < bvec->bv_len) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment