Commit bafc0dba authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

buffer, writeback: make __block_write_full_page() honor cgroup writeback

[__]block_write_full_page() is used to implement ->writepage in
various filesystems.  All writeback logic is now updated to handle
cgroup writeback and the block cgroup to issue IOs for is encoded in
writeback_control and can be retrieved from the inode; however,
[__]block_write_full_page() currently ignores the blkcg indicated by
inode and issues all bio's without explicit blkcg association.

This patch adds submit_bh_blkcg() which associates the bio with the
specified blkio cgroup before issuing and uses it in
__block_write_full_page() so that the issued bio's are associated with
inode_to_wb_blkcg_css(inode).

v2: Updated for per-inode wb association.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 0747259d
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/backing-dev.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/suspend.h> #include <linux/suspend.h>
...@@ -44,6 +45,9 @@ ...@@ -44,6 +45,9 @@
#include <trace/events/block.h> #include <trace/events/block.h>
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
static int submit_bh_blkcg(int rw, struct buffer_head *bh,
unsigned long bio_flags,
struct cgroup_subsys_state *blkcg_css);
#define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers) #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
...@@ -1704,8 +1708,8 @@ static int __block_write_full_page(struct inode *inode, struct page *page, ...@@ -1704,8 +1708,8 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
unsigned int blocksize, bbits; unsigned int blocksize, bbits;
int nr_underway = 0; int nr_underway = 0;
int write_op = (wbc->sync_mode == WB_SYNC_ALL ? int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);
WRITE_SYNC : WRITE); struct cgroup_subsys_state *blkcg_css = inode_to_wb_blkcg_css(inode);
head = create_page_buffers(page, inode, head = create_page_buffers(page, inode,
(1 << BH_Dirty)|(1 << BH_Uptodate)); (1 << BH_Dirty)|(1 << BH_Uptodate));
...@@ -1794,7 +1798,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, ...@@ -1794,7 +1798,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
do { do {
struct buffer_head *next = bh->b_this_page; struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) { if (buffer_async_write(bh)) {
submit_bh(write_op, bh); submit_bh_blkcg(write_op, bh, 0, blkcg_css);
nr_underway++; nr_underway++;
} }
bh = next; bh = next;
...@@ -1848,7 +1852,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, ...@@ -1848,7 +1852,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
struct buffer_head *next = bh->b_this_page; struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) { if (buffer_async_write(bh)) {
clear_buffer_dirty(bh); clear_buffer_dirty(bh);
submit_bh(write_op, bh); submit_bh_blkcg(write_op, bh, 0, blkcg_css);
nr_underway++; nr_underway++;
} }
bh = next; bh = next;
...@@ -3013,7 +3017,9 @@ void guard_bio_eod(int rw, struct bio *bio) ...@@ -3013,7 +3017,9 @@ void guard_bio_eod(int rw, struct bio *bio)
} }
} }
int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) static int submit_bh_blkcg(int rw, struct buffer_head *bh,
unsigned long bio_flags,
struct cgroup_subsys_state *blkcg_css)
{ {
struct bio *bio; struct bio *bio;
...@@ -3035,6 +3041,9 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) ...@@ -3035,6 +3041,9 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
*/ */
bio = bio_alloc(GFP_NOIO, 1); bio = bio_alloc(GFP_NOIO, 1);
if (blkcg_css)
bio_associate_blkcg(bio, blkcg_css);
bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
bio->bi_bdev = bh->b_bdev; bio->bi_bdev = bh->b_bdev;
bio->bi_io_vec[0].bv_page = bh->b_page; bio->bi_io_vec[0].bv_page = bh->b_page;
...@@ -3059,11 +3068,16 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) ...@@ -3059,11 +3068,16 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
submit_bio(rw, bio); submit_bio(rw, bio);
return 0; return 0;
} }
int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
{
return submit_bh_blkcg(rw, bh, bio_flags, NULL);
}
EXPORT_SYMBOL_GPL(_submit_bh); EXPORT_SYMBOL_GPL(_submit_bh);
int submit_bh(int rw, struct buffer_head *bh) int submit_bh(int rw, struct buffer_head *bh)
{ {
return _submit_bh(rw, bh, 0); return submit_bh_blkcg(rw, bh, 0, NULL);
} }
EXPORT_SYMBOL(submit_bh); EXPORT_SYMBOL(submit_bh);
......
...@@ -393,6 +393,12 @@ static inline struct bdi_writeback *inode_to_wb(struct inode *inode) ...@@ -393,6 +393,12 @@ static inline struct bdi_writeback *inode_to_wb(struct inode *inode)
return inode->i_wb; return inode->i_wb;
} }
static inline struct cgroup_subsys_state *
inode_to_wb_blkcg_css(struct inode *inode)
{
return inode_to_wb(inode)->blkcg_css;
}
struct wb_iter { struct wb_iter {
int start_blkcg_id; int start_blkcg_id;
struct radix_tree_iter tree_iter; struct radix_tree_iter tree_iter;
...@@ -510,6 +516,12 @@ static inline void wb_blkcg_offline(struct blkcg *blkcg) ...@@ -510,6 +516,12 @@ static inline void wb_blkcg_offline(struct blkcg *blkcg)
{ {
} }
static inline struct cgroup_subsys_state *
inode_to_wb_blkcg_css(struct inode *inode)
{
return blkcg_root_css;
}
struct wb_iter { struct wb_iter {
int next_id; int next_id;
}; };
......
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