f2fs: implement cgroup writeback support
authorYufen Yu <yuyufen@huawei.com>
Tue, 9 Jan 2018 11:33:39 +0000 (19:33 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Sat, 27 Jan 2018 21:30:03 +0000 (13:30 -0800)
Cgroup writeback requires explicit support from the filesystem.
f2fs's data and node writeback IOs go through __write_data_page,
which sets fio for submiting IOs. So, we add io_wbc for fio,
associate bios with blkcg by invoking wbc_init_bio() and
account IOs issuing by wbc_account_io().
In addtion, f2fs_fill_super() is updated to set SB_I_CGROUPWB.

Meta writeback IOs is left alone by this patch and will always be
attributed to the root cgroup.

The results show that f2fs can throttle writeback nicely for
data writing and file creating.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Yufen Yu <yuyufen@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/node.c
fs/f2fs/super.c

index d078c9bafadab9739b1beda13467d347927789fa..8b6c71bd0893838638552d00b73663f237d278a6 100644 (file)
@@ -170,6 +170,7 @@ static bool __same_bdev(struct f2fs_sb_info *sbi,
  * Low-level block read/write IO operations.
  */
 static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
+                               struct writeback_control *wbc,
                                int npages, bool is_read)
 {
        struct bio *bio;
@@ -179,6 +180,8 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
        f2fs_target_device(sbi, blk_addr, bio);
        bio->bi_end_io = is_read ? f2fs_read_end_io : f2fs_write_end_io;
        bio->bi_private = is_read ? NULL : sbi;
+       if (wbc)
+               wbc_init_bio(wbc, bio);
 
        return bio;
 }
@@ -374,7 +377,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
        f2fs_trace_ios(fio, 0);
 
        /* Allocate a new bio */
-       bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->op));
+       bio = __bio_alloc(fio->sbi, fio->new_blkaddr, fio->io_wbc,
+                               1, is_read_io(fio->op));
 
        if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
                bio_put(bio);
@@ -436,7 +440,7 @@ alloc_new:
                        dec_page_count(sbi, WB_DATA_TYPE(bio_page));
                        goto out_fail;
                }
-               io->bio = __bio_alloc(sbi, fio->new_blkaddr,
+               io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc,
                                                BIO_MAX_PAGES, false);
                io->fio = *fio;
        }
@@ -446,6 +450,9 @@ alloc_new:
                goto alloc_new;
        }
 
+       if (fio->io_wbc)
+               wbc_account_io(fio->io_wbc, bio_page, PAGE_SIZE);
+
        io->last_block_in_bio = fio->new_blkaddr;
        f2fs_trace_ios(fio, 0);
 
@@ -1529,6 +1536,7 @@ static int __write_data_page(struct page *page, bool *submitted,
                .submitted = false,
                .need_lock = LOCK_RETRY,
                .io_type = io_type,
+               .io_wbc = wbc,
        };
 
        trace_f2fs_writepage(page, DATA);
index 880bc8f7de04e45b1d0f49c9810a63804c02a7c3..42daaeb60e06516d4efd2a55b9140e2b43747f33 100644 (file)
@@ -961,6 +961,7 @@ struct f2fs_io_info {
        int need_lock;          /* indicate we need to lock cp_rwsem */
        bool in_list;           /* indicate fio is in io_list */
        enum iostat_type io_type;       /* io type */
+       struct writeback_control *io_wbc; /* writeback control */
 };
 
 #define is_read_io(rw) ((rw) == READ)
index 5d15581ad3fe8b755f231d8414417f11e2927bcf..c6077ba816a0306cf412e1b89ca142447cb24b58 100644 (file)
@@ -1339,6 +1339,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                .encrypted_page = NULL,
                .submitted = false,
                .io_type = io_type,
+               .io_wbc = wbc,
        };
 
        trace_f2fs_writepage(page, NODE);
index c658f31dc09d116c7a5b6de35927fa03d903eac7..789a764ecbb3a6c598d0dff34b4b155f8844a746 100644 (file)
@@ -2518,6 +2518,7 @@ try_onemore:
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
                (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
        memcpy(&sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));
+       sb->s_iflags |= SB_I_CGROUPWB;
 
        /* init f2fs-specific super block info */
        sbi->valid_super_block = valid_super_block;