From: Tang Yizhou <yizhou.tang@xxxxxxxxxx> Since commit 1a12d8bd7b29 ("writeback: scale IO chunk size up to half device bandwidth"), macro MAX_WRITEBACK_PAGES has been removed from the writeback path. Therefore, the MAX_WRITEBACK_PAGES comments in xfs_direct_write_iomap_begin() and xfs_buffered_write_iomap_begin() appear outdated. In addition, Christoph mentioned that the xfs iomap process should be similar to writeback, so xfs_max_map_length() was written following the logic of writeback_chunk_size(). v2: Thanks for Christoph's advice. Resync with the writeback code. Signed-off-by: Tang Yizhou <yizhou.tang@xxxxxxxxxx> --- fs/fs-writeback.c | 5 ---- fs/xfs/xfs_iomap.c | 52 ++++++++++++++++++++++++--------------- include/linux/writeback.h | 5 ++++ 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index d8bec3c1bb1f..31c72e207e1b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -31,11 +31,6 @@ #include <linux/memcontrol.h> #include "internal.h" -/* - * 4MB minimal write chunk size - */ -#define MIN_WRITEBACK_PAGES (4096UL >> (PAGE_SHIFT - 10)) - /* * Passed into wb_writeback(), essentially a subset of writeback_control */ diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 1e11f48814c0..80f759fa9534 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -4,6 +4,8 @@ * Copyright (c) 2016-2018 Christoph Hellwig. * All Rights Reserved. */ +#include <linux/writeback.h> + #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" @@ -744,6 +746,34 @@ xfs_ilock_for_iomap( return 0; } +/* + * We cap the maximum length we map to a sane size to keep the chunks + * of work done where somewhat symmetric with the work writeback does. + * This is a completely arbitrary number pulled out of thin air as a + * best guess for initial testing. + * + * Following the logic of writeback_chunk_size(), the length will be + * rounded to the nearest 4MB boundary. + * + * Note that the values needs to be less than 32-bits wide until the + * lower level functions are updated. + */ +static loff_t +xfs_max_map_length(struct inode *inode, loff_t length) +{ + struct bdi_writeback *wb; + long pages; + + spin_lock(&inode->i_lock); + wb = inode_to_wb(wb); + pages = min(wb->avg_write_bandwidth / 2, + global_wb_domain.dirty_limit / DIRTY_SCOPE); + spin_unlock(&inode->i_lock); + pages = round_down(pages + MIN_WRITEBACK_PAGES, MIN_WRITEBACK_PAGES); + + return min_t(loff_t, length, pages * PAGE_SIZE); +} + /* * Check that the imap we are going to return to the caller spans the entire * range that the caller requested for the IO. @@ -878,16 +908,7 @@ xfs_direct_write_iomap_begin( if (flags & (IOMAP_NOWAIT | IOMAP_OVERWRITE_ONLY)) goto out_unlock; - /* - * We cap the maximum length we map to a sane size to keep the chunks - * of work done where somewhat symmetric with the work writeback does. - * This is a completely arbitrary number pulled out of thin air as a - * best guess for initial testing. - * - * Note that the values needs to be less than 32-bits wide until the - * lower level functions are updated. - */ - length = min_t(loff_t, length, 1024 * PAGE_SIZE); + length = xfs_max_map_length(inode, length); end_fsb = xfs_iomap_end_fsb(mp, offset, length); if (offset + length > XFS_ISIZE(ip)) @@ -1096,16 +1117,7 @@ xfs_buffered_write_iomap_begin( allocfork = XFS_COW_FORK; end_fsb = imap.br_startoff + imap.br_blockcount; } else { - /* - * We cap the maximum length we map here to MAX_WRITEBACK_PAGES - * pages to keep the chunks of work done where somewhat - * symmetric with the work writeback does. This is a completely - * arbitrary number pulled out of thin air. - * - * Note that the values needs to be less than 32-bits wide until - * the lower level functions are updated. - */ - count = min_t(loff_t, count, 1024 * PAGE_SIZE); + count = xfs_max_map_length(inode, count); end_fsb = xfs_iomap_end_fsb(mp, offset, count); if (xfs_is_always_cow_inode(ip)) diff --git a/include/linux/writeback.h b/include/linux/writeback.h index d6db822e4bb3..657bc4dd22d0 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -17,6 +17,11 @@ struct bio; DECLARE_PER_CPU(int, dirty_throttle_leaks); +/* + * 4MB minimal write chunk size + */ +#define MIN_WRITEBACK_PAGES (4096UL >> (PAGE_SHIFT - 10)) + /* * The global dirty threshold is normally equal to the global dirty limit, * except when the system suddenly allocates a lot of anonymous memory and -- 2.25.1