Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1381246 > unrolled thread

[PATCHSET v4 0/8] Make background writeback not suck

Started byJens Axboe <axboe@fb.com>
First post2016-04-18 06:30 +0200
Last post2016-04-26 17:10 +0200
Articles 4 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCHSET v4 0/8] Make background writeback not suck Jens Axboe <axboe@fb.com> - 2016-04-18 06:30 +0200
    [PATCH 4/8] writeback: track if we're sleeping on progress in balance_dirty_pages() Jens Axboe <axboe@fb.com> - 2016-04-18 06:30 +0200
    [PATCH 1/8] block: add WRITE_BG Jens Axboe <axboe@fb.com> - 2016-04-18 06:30 +0200
    Re: [PATCHSET v4 0/8] Make background writeback not suck Jens Axboe <axboe@fb.com> - 2016-04-26 17:10 +0200

#1381246 — [PATCHSET v4 0/8] Make background writeback not suck

FromJens Axboe <axboe@fb.com>
Date2016-04-18 06:30 +0200
Subject[PATCHSET v4 0/8] Make background writeback not suck
Message-ID<rp8YW-7TI-9@gated-at.bofh.it>
Hi,

Since the dawn of time, our background buffered writeback has sucked.
When we do background buffered writeback, it should have little impact
on foreground activity. That's the definition of background activity...
But for as long as I can remember, heavy buffered writers have not
behaved like that. For instance, if I do something like this:

$ dd if=/dev/zero of=foo bs=1M count=10k

on my laptop, and then try and start chrome, it basically won't start
before the buffered writeback is done. Or, for server oriented
workloads, where installation of a big RPM (or similar) adversely
impacts database reads or sync writes. When that happens, I get people
yelling at me.

I have posted plenty of results previously, I'll keep it shorter
this time. Here's a run on my laptop, using read-to-pipe-async for
reading a 5g file, and rewriting it.

4.6-rc3:

$ t/read-to-pipe-async -f ~/5g > 5g-new

Latency percentiles (usec) (READERS)
	50.0000th: 2
	75.0000th: 3
	90.0000th: 5
	95.0000th: 7
	99.0000th: 43
	99.5000th: 77
	99.9000th: 9008
	99.9900th: 91008
	99.9990th: 286208
	99.9999th: 347648
	Over=1251, min=0, max=358081
Latency percentiles (usec) (WRITERS)
	50.0000th: 4
	75.0000th: 8
	90.0000th: 13
	95.0000th: 15
	99.0000th: 32
	99.5000th: 43
	99.9000th: 81
	99.9900th: 2372
	99.9990th: 104320
	99.9999th: 349696
	Over=63, min=1, max=358321
Read rate (KB/sec) : 91859
Write rate (KB/sec): 91859

4.6-rc3 + wb-buf-throttle

Latency percentiles (usec) (READERS)
	50.0000th: 2
	75.0000th: 3
	90.0000th: 5
	95.0000th: 8
	99.0000th: 48
	99.5000th: 79
	99.9000th: 5304
	99.9900th: 22496
	99.9990th: 29408
	99.9999th: 33728
	Over=860, min=0, max=37599
Latency percentiles (usec) (WRITERS)
	50.0000th: 4
	75.0000th: 9
	90.0000th: 14
	95.0000th: 16
	99.0000th: 34
	99.5000th: 45
	99.9000th: 87
	99.9900th: 1342
	99.9990th: 13648
	99.9999th: 21280
	Over=29, min=1, max=30457
Read rate (KB/sec) : 95832
Write rate (KB/sec): 95832

Better throughput and tighter latencies, for both reads and writes.
That's hard not to like.

The above was the why. The how is basically throttling background
writeback. We still want to issue big writes from the vm side of things,
so we get nice and big extents on the file system end. But we don't need
to flood the device with THOUSANDS of requests for background writeback.
For most devices, we don't need a whole lot to get decent throughput.

This adds some simple blk-wb code that keeps limits how much buffered
writeback we keep in flight on the device end. It's all about managing
the queues on the hardware side. The big change in this version is that
it should be pretty much auto-tuning - you no longer have to set a
given percentage of writeback bandwidth. I've implemented something
similar to CoDel to manage the writeback queue. See the last patch
for a full description, but the tldr is that we monitor min latencies
over a window of time, and scale up/down the queue based on that. This
needs a minimum of tunables, and it stays out of the way, if your device
is fast enough. There's a single tunable now, wb_last_usec, that simply
sets this latency target. Most people won't have to touch this, it'll
work pretty well just being in the ballpark.

I welcome testing. If you are sick of Linux bogging down when buffered
writes are happening, then this is for you, laptop or server. The
patchset is fully stable, I have not observed problems. It passes full
xfstest runs, and a variety of benchmarks as well. It works equally well
on blk-mq/scsi-mq, and "classic" setups.

You can also find this in a branch in the block git repo:

git://git.kernel.dk/linux-block.git wb-buf-throttle

Note that I rebase this branch when I collapse patches. The
wb-buf-throttle-v4 will remain the same as this version. I've folded
the device write cache changes into my 4.7 branches, so they are not
a part of this posting. Get the full wb-buf-throttle branch, or apply
the patches here on top of my for-next. A full patch against Linus'
current tree can also be downloaded here:

http://brick.kernel.dk/snaps/wb-buf-throttle-v4.patch

Changes since v3

- Re-do the mm/ writheback parts. Add REQ_BG for background writes,
  and don't overload the wbc 'reason' for writeback decisions.
- Add tracking for when apps are sleeping waiting for a page to complete.
- Change wbc_to_write() to wbc_to_write_cmd().
- Use atomic_t for the balance_dirty_pages() sleep count.
- Add a basic scalable block stats tracking framework.
- Rewrite blk-wb core as described above, to dynamically adapt. This is
  a big change, see the last patch for a full description of it.
- Add tracing to blk-wb, instead of using debug printk's.
- Rebased to 4.6-rc3 (ish)

Changes since v2

- Switch from wb_depth to wb_percent, as that's an easier tunable.
- Add the patch to track device depth on the block layer side.
- Cleanup the limiting code.
- Don't use a fixed limit in the wb wait, since it can change
  between wakeups.
- Minor tweaks, fixups, cleanups.

Changes since v1

- Drop sync() WB_SYNC_NONE -> WB_SYNC_ALL change
- wb_start_writeback() fills in background/reclaim/sync info in
  the writeback work, based on writeback reason.
- Use WRITE_SYNC for reclaim/sync IO
- Split balance_dirty_pages() sleep change into separate patch
- Drop get_request() u64 flag change, set the bit on the request
  directly after-the-fact.
- Fix wrong sysfs return value
- Various small cleanups


 Documentation/block/queue-sysfs.txt             |    9 
 Documentation/block/writeback_cache_control.txt |    4 
 arch/um/drivers/ubd_kern.c                      |    2 
 block/Makefile                                  |    2 
 block/blk-core.c                                |   22 +
 block/blk-flush.c                               |   11 
 block/blk-mq-sysfs.c                            |   47 ++
 block/blk-mq.c                                  |   45 ++
 block/blk-mq.h                                  |    3 
 block/blk-settings.c                            |   58 +-
 block/blk-stat.c                                |  184 ++++++++
 block/blk-stat.h                                |   17 
 block/blk-sysfs.c                               |  122 +++++
 block/blk-wb.c                                  |  495 ++++++++++++++++++++++++
 block/blk-wb.h                                  |   42 ++
 drivers/block/drbd/drbd_main.c                  |    2 
 drivers/block/loop.c                            |    2 
 drivers/block/mtip32xx/mtip32xx.c               |    6 
 drivers/block/nbd.c                             |    4 
 drivers/block/osdblk.c                          |    2 
 drivers/block/ps3disk.c                         |    2 
 drivers/block/skd_main.c                        |    2 
 drivers/block/virtio_blk.c                      |    6 
 drivers/block/xen-blkback/xenbus.c              |    2 
 drivers/block/xen-blkfront.c                    |    3 
 drivers/ide/ide-disk.c                          |    6 
 drivers/md/bcache/super.c                       |    2 
 drivers/md/dm-table.c                           |   20 
 drivers/md/md.c                                 |    2 
 drivers/md/raid5-cache.c                        |    3 
 drivers/mmc/card/block.c                        |    2 
 drivers/mtd/mtd_blkdevs.c                       |    2 
 drivers/nvme/host/core.c                        |    7 
 drivers/scsi/scsi.c                             |    3 
 drivers/scsi/sd.c                               |    8 
 drivers/target/target_core_iblock.c             |    6 
 fs/block_dev.c                                  |    2 
 fs/buffer.c                                     |    2 
 fs/f2fs/data.c                                  |    2 
 fs/f2fs/node.c                                  |    2 
 fs/gfs2/meta_io.c                               |    3 
 fs/mpage.c                                      |    9 
 fs/xfs/xfs_aops.c                               |    2 
 include/linux/backing-dev-defs.h                |    2 
 include/linux/blk_types.h                       |   14 
 include/linux/blkdev.h                          |   27 +
 include/linux/fs.h                              |    4 
 include/linux/writeback.h                       |   10 
 include/trace/events/block.h                    |   98 ++++
 mm/backing-dev.c                                |    1 
 mm/filemap.c                                    |   42 +-
 mm/page-writeback.c                             |    2 
 52 files changed, 1281 insertions(+), 96 deletions(-)

-- 
Jens Axboe

[toc] | [next] | [standalone]


#1381247 — [PATCH 4/8] writeback: track if we're sleeping on progress in balance_dirty_pages()

FromJens Axboe <axboe@fb.com>
Date2016-04-18 06:30 +0200
Subject[PATCH 4/8] writeback: track if we're sleeping on progress in balance_dirty_pages()
Message-ID<rp8YW-7TI-27@gated-at.bofh.it>
In reply to#1381246
Note in the bdi_writeback structure if a task is currently being
limited in balance_dirty_pages(), waiting for writeback to
proceed.

Signed-off-by: Jens Axboe <axboe@fb.com>
---
 include/linux/backing-dev-defs.h | 2 ++
 mm/backing-dev.c                 | 1 +
 mm/page-writeback.c              | 2 ++
 3 files changed, 5 insertions(+)

diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 3f103076d0bf..1212c374b928 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -116,6 +116,8 @@ struct bdi_writeback {
 	struct list_head work_list;
 	struct delayed_work dwork;	/* work item used for writeback */
 
+	atomic_t dirty_sleeping;	/* waiting on dirty limit exceeded */
+
 	struct list_head bdi_node;	/* anchored at bdi->wb_list */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 0c6317b7db38..41db7dff11d0 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -310,6 +310,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
 	spin_lock_init(&wb->work_lock);
 	INIT_LIST_HEAD(&wb->work_list);
 	INIT_DELAYED_WORK(&wb->dwork, wb_workfn);
+	atomic_set(&wb->dirty_sleeping, 0);
 
 	wb->congested = wb_congested_get_create(bdi, blkcg_id, gfp);
 	if (!wb->congested)
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 999792d35ccc..028a3d4d7129 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1746,7 +1746,9 @@ pause:
 					  pause,
 					  start_time);
 		__set_current_state(TASK_KILLABLE);
+		atomic_inc(&wb->dirty_sleeping);
 		io_schedule_timeout(pause);
+		atomic_dec(&wb->dirty_sleeping);
 
 		current->dirty_paused_when = now + pause;
 		current->nr_dirtied = 0;
-- 
2.8.0.rc4.6.g7e4ba36

[toc] | [prev] | [next] | [standalone]


#1381248 — [PATCH 1/8] block: add WRITE_BG

FromJens Axboe <axboe@fb.com>
Date2016-04-18 06:30 +0200
Subject[PATCH 1/8] block: add WRITE_BG
Message-ID<rp8YX-7TI-31@gated-at.bofh.it>
In reply to#1381246
This adds a new request flag, REQ_BG, that callers can use to tell
the block layer that this is background (non-urgent) IO.

Signed-off-by: Jens Axboe <axboe@fb.com>
---
 include/linux/blk_types.h | 4 +++-
 include/linux/fs.h        | 4 ++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 86a38ea1823f..223012451c7a 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -161,6 +161,7 @@ enum rq_flag_bits {
 	__REQ_INTEGRITY,	/* I/O includes block integrity payload */
 	__REQ_FUA,		/* forced unit access */
 	__REQ_FLUSH,		/* request for cache flush */
+	__REQ_BG,		/* background activity */
 
 	/* bio only flags */
 	__REQ_RAHEAD,		/* read ahead, can fail anytime */
@@ -208,7 +209,7 @@ enum rq_flag_bits {
 #define REQ_COMMON_MASK \
 	(REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \
 	 REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \
-	 REQ_SECURE | REQ_INTEGRITY)
+	 REQ_SECURE | REQ_INTEGRITY | REQ_BG)
 #define REQ_CLONE_MASK		REQ_COMMON_MASK
 
 #define BIO_NO_ADVANCE_ITER_MASK	(REQ_DISCARD|REQ_WRITE_SAME)
@@ -235,6 +236,7 @@ enum rq_flag_bits {
 #define REQ_COPY_USER		(1ULL << __REQ_COPY_USER)
 #define REQ_FLUSH		(1ULL << __REQ_FLUSH)
 #define REQ_FLUSH_SEQ		(1ULL << __REQ_FLUSH_SEQ)
+#define REQ_BG			(1ULL << __REQ_BG)
 #define REQ_IO_STAT		(1ULL << __REQ_IO_STAT)
 #define REQ_MIXED_MERGE		(1ULL << __REQ_MIXED_MERGE)
 #define REQ_SECURE		(1ULL << __REQ_SECURE)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 70e61b58baaf..bb8f951cc619 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -192,6 +192,9 @@ typedef void (dax_iodone_t)(struct buffer_head *bh_map, int uptodate);
  * WRITE_FLUSH_FUA	Combination of WRITE_FLUSH and FUA. The IO is preceded
  *			by a cache flush and data is guaranteed to be on
  *			non-volatile media on completion.
+ * WRITE_BG		Background write. This is for background activity like
+ *			the periodic flush and background threshold writeback
+ *
  *
  */
 #define RW_MASK			REQ_WRITE
@@ -207,6 +210,7 @@ typedef void (dax_iodone_t)(struct buffer_head *bh_map, int uptodate);
 #define WRITE_FLUSH		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH)
 #define WRITE_FUA		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA)
 #define WRITE_FLUSH_FUA		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
+#define WRITE_BG		(WRITE | REQ_NOIDLE | REQ_BG)
 
 /*
  * Attribute flags.  These should be or-ed together to figure out what
-- 
2.8.0.rc4.6.g7e4ba36

[toc] | [prev] | [next] | [standalone]


#1387590

FromJens Axboe <axboe@fb.com>
Date2016-04-26 17:10 +0200
Message-ID<rscMG-1n6-11@gated-at.bofh.it>
In reply to#1381246
On 04/26/2016 01:04 AM, Sedat Dilek wrote:
> Hi Jens,
>
> I am testing current linux-block.git#wb-buf-throttle on top of Linux
> v4.6-rc5 here on my Ubuntu/precise AMD64.
> ( Was installed as a WUBI "test" system - "testing" since April 2012 :-) .)

Great! Thanks for testing.

> Here are some numbers:
>
> # df -T | egrep  'sda|loop'
> /dev/sda2      fuseblk  465546236 210981868 254564368   46% /host
> /dev/loop0     ext4      17753424  15586612   1241936   93% /
>
> # egrep 'sda|loop|ext4' /etc/fstab
> /host/ubuntu/disks/root.disk    /               ext4
> loop,errors=remount-ro  0       1
> /host/ubuntu/disks/swap.disk    none            swap    loop,sw
>           0       0

What kind of device is sda?

> ( Not sure why I cannot do a find on /sys/block/ .)

Probably the symlinks that confuse it.

> # find /sys/devices/ -name '*wb_stat*' | egrep 'loop0|sda'
> /sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda/queue/wb_stats
> /sys/devices/virtual/block/loop0/queue/wb_stats
>
> # find /sys/devices/ -name '*wb_lat*' | egrep 'loop0|sda'
> /sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda/queue/wb_lat_usec
> /sys/devices/virtual/block/loop0/queue/wb_lat_usec
>
> # cat /sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda/queue/wb_stats
> /sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda/queue/wb_lat_usec
> background=8, normal=16, max=31, inflight=0, wait=0, bdp_wait=0
> 75000
>
> # cat /sys/devices/virtual/block/loop0/queue/wb_stats
> /sys/devices/virtual/block/loop0/queue/wb_lat_usec
> background=16, normal=32, max=64, inflight=0, wait=0, bdp_wait=0
> 75000
>
> Questions...
>
> Planning a v5?

Yes, I'll post a v5 today or something like that. Functionally not a 
huge amount of changes, but it does have a few important bug fixes that 
make it perform better. The biggest part is making it generic, so it can 
be plugged into NFS as well, for instance.

> Will this go to Linux v4.7 or later?
> How should someone test?

Probably a bit too tight for 4.7, but one can always hope. 4.8 is 
probably a more realistic target.

Testing is really having some readers while you have writes going on. 
One example is doing something that reads while you have a dd writing to 
your device. Or interactive feel while installing a lot of packages, 
which tends to generate a ton of writes as well.

If you are so inclined, I'd encourage you to test the v5 I'll post later 
today. I've run that through the paces on various devices.

> Documentation...
>
> Can you add some more docs about getting infos (see above cat#s etc.)
> below Documentation/ directory?
> ( Talking about the stuff you have embedded in the commit-messages. )

Yeah, I'll do that, it is a bit light right now. It'll be in the next 
release.


-- 
Jens Axboe

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web