aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2015-07-02 16:57:22 -0400
committerChris Mason <clm@fb.com>2015-08-09 10:35:06 -0400
commitda2f0f74cf7d074e5a8918c8efdf6aba4a989b4a (patch)
tree3a2cf977b893863ce5938132a802804a56291f05
parenta4027a20c57a2c8779e17a61425737634bb7163d (diff)
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: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/disk-io.c1
-rw-r--r--fs/btrfs/extent_io.c16
-rw-r--r--fs/btrfs/inode.c6
-rw-r--r--fs/btrfs/super.c1
-rw-r--r--fs/btrfs/volumes.c8
5 files changed, 28 insertions, 4 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index f7536bcf7cee..230546b45474 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1724,6 +1724,7 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
1724 bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE; 1724 bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE;
1725 bdi->congested_fn = btrfs_congested_fn; 1725 bdi->congested_fn = btrfs_congested_fn;
1726 bdi->congested_data = info; 1726 bdi->congested_data = info;
1727 bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK;
1727 return 0; 1728 return 0;
1728} 1729}
1729 1730
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 02d05817cbdf..b9755ce98218 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2730,6 +2730,9 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
2730 btrfs_bio->csum = NULL; 2730 btrfs_bio->csum = NULL;
2731 btrfs_bio->csum_allocated = NULL; 2731 btrfs_bio->csum_allocated = NULL;
2732 btrfs_bio->end_io = NULL; 2732 btrfs_bio->end_io = NULL;
2733 /* FIXME, put this into bio_clone_bioset */
2734 if (bio->bi_css)
2735 bio_associate_blkcg(new, bio->bi_css);
2733 } 2736 }
2734 return new; 2737 return new;
2735} 2738}
@@ -2790,6 +2793,7 @@ static int merge_bio(int rw, struct extent_io_tree *tree, struct page *page,
2790} 2793}
2791 2794
2792static int submit_extent_page(int rw, struct extent_io_tree *tree, 2795static int submit_extent_page(int rw, struct extent_io_tree *tree,
2796 struct writeback_control *wbc,
2793 struct page *page, sector_t sector, 2797 struct page *page, sector_t sector,
2794 size_t size, unsigned long offset, 2798 size_t size, unsigned long offset,
2795 struct block_device *bdev, 2799 struct block_device *bdev,
@@ -2826,6 +2830,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
2826 } 2830 }
2827 bio = NULL; 2831 bio = NULL;
2828 } else { 2832 } else {
2833 if (wbc)
2834 wbc_account_io(wbc, page, page_size);
2829 return 0; 2835 return 0;
2830 } 2836 }
2831 } 2837 }
@@ -2841,6 +2847,10 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
2841 bio_add_page(bio, page, page_size, offset); 2847 bio_add_page(bio, page, page_size, offset);
2842 bio->bi_end_io = end_io_func; 2848 bio->bi_end_io = end_io_func;
2843 bio->bi_private = tree; 2849 bio->bi_private = tree;
2850 if (wbc) {
2851 wbc_init_bio(wbc, bio);
2852 wbc_account_io(wbc, page, page_size);
2853 }
2844 2854
2845 if (bio_ret) 2855 if (bio_ret)
2846 *bio_ret = bio; 2856 *bio_ret = bio;
@@ -3051,7 +3061,7 @@ static int __do_readpage(struct extent_io_tree *tree,
3051 } 3061 }
3052 3062
3053 pnr -= page->index; 3063 pnr -= page->index;
3054 ret = submit_extent_page(rw, tree, page, 3064 ret = submit_extent_page(rw, tree, NULL, page,
3055 sector, disk_io_size, pg_offset, 3065 sector, disk_io_size, pg_offset,
3056 bdev, bio, pnr, 3066 bdev, bio, pnr,
3057 end_bio_extent_readpage, mirror_num, 3067 end_bio_extent_readpage, mirror_num,
@@ -3446,7 +3456,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode,
3446 page->index, cur, end); 3456 page->index, cur, end);
3447 } 3457 }
3448 3458
3449 ret = submit_extent_page(write_flags, tree, page, 3459 ret = submit_extent_page(write_flags, tree, wbc, page,
3450 sector, iosize, pg_offset, 3460 sector, iosize, pg_offset,
3451 bdev, &epd->bio, max_nr, 3461 bdev, &epd->bio, max_nr,
3452 end_bio_extent_writepage, 3462 end_bio_extent_writepage,
@@ -3749,7 +3759,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
3749 3759
3750 clear_page_dirty_for_io(p); 3760 clear_page_dirty_for_io(p);
3751 set_page_writeback(p); 3761 set_page_writeback(p);
3752 ret = submit_extent_page(rw, tree, p, offset >> 9, 3762 ret = submit_extent_page(rw, tree, wbc, p, offset >> 9,
3753 PAGE_CACHE_SIZE, 0, bdev, &epd->bio, 3763 PAGE_CACHE_SIZE, 0, bdev, &epd->bio,
3754 -1, end_bio_extent_buffer_writepage, 3764 -1, end_bio_extent_buffer_writepage,
3755 0, epd->bio_flags, bio_flags); 3765 0, epd->bio_flags, bio_flags);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 79a73645346e..bda3c41dc9d5 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7987,7 +7987,11 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
7987 u64 first_sector, gfp_t gfp_flags) 7987 u64 first_sector, gfp_t gfp_flags)
7988{ 7988{
7989 int nr_vecs = bio_get_nr_vecs(bdev); 7989 int nr_vecs = bio_get_nr_vecs(bdev);
7990 return btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags); 7990 struct bio *bio;
7991 bio = btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags);
7992 if (bio)
7993 bio_associate_current(bio);
7994 return bio;
7991} 7995}
7992 7996
7993static inline int btrfs_lookup_and_bind_dio_csum(struct btrfs_root *root, 7997static inline int btrfs_lookup_and_bind_dio_csum(struct btrfs_root *root,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index cd7ef34d2dce..d366dd4664d0 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1033,6 +1033,7 @@ static int btrfs_fill_super(struct super_block *sb,
1033 sb->s_flags |= MS_POSIXACL; 1033 sb->s_flags |= MS_POSIXACL;
1034#endif 1034#endif
1035 sb->s_flags |= MS_I_VERSION; 1035 sb->s_flags |= MS_I_VERSION;
1036 sb->s_iflags |= SB_I_CGROUPWB;
1036 err = open_ctree(sb, fs_devices, (char *)data); 1037 err = open_ctree(sb, fs_devices, (char *)data);
1037 if (err) { 1038 if (err) {
1038 printk(KERN_ERR "BTRFS: open_ctree failed\n"); 1039 printk(KERN_ERR "BTRFS: open_ctree failed\n");
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index fb9abf1678d0..88e2fe931bde 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5942,6 +5942,14 @@ again:
5942 if (!bio) 5942 if (!bio)
5943 return -ENOMEM; 5943 return -ENOMEM;
5944 5944
5945 if (first_bio->bi_ioc) {
5946 get_io_context_active(first_bio->bi_ioc);
5947 bio->bi_ioc = first_bio->bi_ioc;
5948 }
5949 if (first_bio->bi_css) {
5950 css_get(first_bio->bi_css);
5951 bio->bi_css = first_bio->bi_css;
5952 }
5945 while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) { 5953 while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) {
5946 if (bio_add_page(bio, bvec->bv_page, bvec->bv_len, 5954 if (bio_add_page(bio, bvec->bv_page, bvec->bv_len,
5947 bvec->bv_offset) < bvec->bv_len) { 5955 bvec->bv_offset) < bvec->bv_len) {