blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
#ifndef WB_THROTTLE_H
|
|
|
|
#define WB_THROTTLE_H
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/atomic.h>
|
|
|
|
#include <linux/wait.h>
|
|
|
|
#include <linux/timer.h>
|
|
|
|
#include <linux/ktime.h>
|
|
|
|
|
|
|
|
#include "blk-stat.h"
|
|
|
|
|
|
|
|
enum wbt_flags {
|
|
|
|
WBT_TRACKED = 1, /* write, tracked for throttling */
|
|
|
|
WBT_READ = 2, /* read */
|
|
|
|
WBT_KSWAPD = 4, /* write, from kswapd */
|
|
|
|
|
|
|
|
WBT_NR_BITS = 3, /* number of bits */
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
WBT_NUM_RWQ = 2,
|
|
|
|
};
|
|
|
|
|
2016-11-28 17:40:34 +01:00
|
|
|
/*
|
|
|
|
* Enable states. Either off, or on by default (done at init time),
|
|
|
|
* or on through manual setup in sysfs.
|
|
|
|
*/
|
|
|
|
enum {
|
|
|
|
WBT_STATE_ON_DEFAULT = 1,
|
|
|
|
WBT_STATE_ON_MANUAL = 2,
|
|
|
|
};
|
|
|
|
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
static inline void wbt_clear_state(struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
stat->time &= BLK_STAT_TIME_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline enum wbt_flags wbt_stat_to_mask(struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
return (stat->time & BLK_STAT_MASK) >> BLK_STAT_SHIFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void wbt_track(struct blk_issue_stat *stat, enum wbt_flags wb_acct)
|
|
|
|
{
|
|
|
|
stat->time |= ((u64) wb_acct) << BLK_STAT_SHIFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool wbt_is_tracked(struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
return (stat->time >> BLK_STAT_SHIFT) & WBT_TRACKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool wbt_is_read(struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
return (stat->time >> BLK_STAT_SHIFT) & WBT_READ;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct rq_wait {
|
|
|
|
wait_queue_head_t wait;
|
|
|
|
atomic_t inflight;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rq_wb {
|
|
|
|
/*
|
|
|
|
* Settings that govern how we throttle
|
|
|
|
*/
|
|
|
|
unsigned int wb_background; /* background writeback */
|
|
|
|
unsigned int wb_normal; /* normal writeback */
|
|
|
|
unsigned int wb_max; /* max throughput writeback */
|
|
|
|
int scale_step;
|
|
|
|
bool scaled_max;
|
|
|
|
|
2016-11-28 17:40:34 +01:00
|
|
|
short enable_state; /* WBT_STATE_* */
|
|
|
|
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
/*
|
|
|
|
* Number of consecutive periods where we don't have enough
|
|
|
|
* information to make a firm scale up/down decision.
|
|
|
|
*/
|
|
|
|
unsigned int unknown_cnt;
|
|
|
|
|
|
|
|
u64 win_nsec; /* default window size */
|
|
|
|
u64 cur_win_nsec; /* current window size */
|
|
|
|
|
blk-stat: convert to callback-based statistics reporting
Currently, statistics are gathered in ~0.13s windows, and users grab the
statistics whenever they need them. This is not ideal for both in-tree
users:
1. Writeback throttling wants its own dynamically sized window of
statistics. Since the blk-stats statistics are reset after every
window and the wbt windows don't line up with the blk-stats windows,
wbt doesn't see every I/O.
2. Polling currently grabs the statistics on every I/O. Again, depending
on how the window lines up, we may miss some I/Os. It's also
unnecessary overhead to get the statistics on every I/O; the hybrid
polling heuristic would be just as happy with the statistics from the
previous full window.
This reworks the blk-stats infrastructure to be callback-based: users
register a callback that they want called at a given time with all of
the statistics from the window during which the callback was active.
Users can dynamically bucketize the statistics. wbt and polling both
currently use read vs. write, but polling can be extended to further
subdivide based on request size.
The callbacks are kept on an RCU list, and each callback has percpu
stats buffers. There will only be a few users, so the overhead on the
I/O completion side is low. The stats flushing is also simplified
considerably: since the timer function is responsible for clearing the
statistics, we don't have to worry about stale statistics.
wbt is a trivial conversion. After the conversion, the windowing problem
mentioned above is fixed.
For polling, we register an extra callback that caches the previous
window's statistics in the struct request_queue for the hybrid polling
heuristic to use.
Since we no longer have a single stats buffer for the request queue,
this also removes the sysfs and debugfs stats entries. To replace those,
we add a debugfs entry for the poll statistics.
Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
2017-03-21 16:56:08 +01:00
|
|
|
struct blk_stat_callback *cb;
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
|
|
|
|
s64 sync_issue;
|
|
|
|
void *sync_cookie;
|
|
|
|
|
|
|
|
unsigned int wc;
|
|
|
|
unsigned int queue_depth;
|
|
|
|
|
|
|
|
unsigned long last_issue; /* last non-throttled issue */
|
|
|
|
unsigned long last_comp; /* last non-throttled comp */
|
|
|
|
unsigned long min_lat_nsec;
|
2016-11-11 05:52:53 +01:00
|
|
|
struct request_queue *queue;
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
struct rq_wait rq_wait[WBT_NUM_RWQ];
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline unsigned int wbt_inflight(struct rq_wb *rwb)
|
|
|
|
{
|
|
|
|
unsigned int i, ret = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < WBT_NUM_RWQ; i++)
|
|
|
|
ret += atomic_read(&rwb->rq_wait[i].inflight);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_BLK_WBT
|
|
|
|
|
|
|
|
void __wbt_done(struct rq_wb *, enum wbt_flags);
|
|
|
|
void wbt_done(struct rq_wb *, struct blk_issue_stat *);
|
|
|
|
enum wbt_flags wbt_wait(struct rq_wb *, struct bio *, spinlock_t *);
|
2016-11-11 05:50:51 +01:00
|
|
|
int wbt_init(struct request_queue *);
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
void wbt_exit(struct request_queue *);
|
|
|
|
void wbt_update_limits(struct rq_wb *);
|
|
|
|
void wbt_requeue(struct rq_wb *, struct blk_issue_stat *);
|
|
|
|
void wbt_issue(struct rq_wb *, struct blk_issue_stat *);
|
2016-11-28 17:25:50 +01:00
|
|
|
void wbt_disable_default(struct request_queue *);
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
|
|
|
|
void wbt_set_queue_depth(struct rq_wb *, unsigned int);
|
|
|
|
void wbt_set_write_cache(struct rq_wb *, bool);
|
|
|
|
|
2016-11-28 17:22:47 +01:00
|
|
|
u64 wbt_default_latency_nsec(struct request_queue *);
|
|
|
|
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
#else
|
|
|
|
|
|
|
|
static inline void __wbt_done(struct rq_wb *rwb, enum wbt_flags flags)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline void wbt_done(struct rq_wb *rwb, struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline enum wbt_flags wbt_wait(struct rq_wb *rwb, struct bio *bio,
|
|
|
|
spinlock_t *lock)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2016-11-11 05:50:51 +01:00
|
|
|
static inline int wbt_init(struct request_queue *q)
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
static inline void wbt_exit(struct request_queue *q)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline void wbt_update_limits(struct rq_wb *rwb)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline void wbt_requeue(struct rq_wb *rwb, struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline void wbt_issue(struct rq_wb *rwb, struct blk_issue_stat *stat)
|
|
|
|
{
|
|
|
|
}
|
2016-11-28 17:25:50 +01:00
|
|
|
static inline void wbt_disable_default(struct request_queue *q)
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline void wbt_set_queue_depth(struct rq_wb *rwb, unsigned int depth)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
static inline void wbt_set_write_cache(struct rq_wb *rwb, bool wc)
|
|
|
|
{
|
|
|
|
}
|
2016-11-28 17:22:47 +01:00
|
|
|
static inline u64 wbt_default_latency_nsec(struct request_queue *q)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
blk-wbt: add general throttling mechanism
We can hook this up to the block layer, to help throttle buffered
writes.
wbt registers a few trace points that can be used to track what is
happening in the system:
wbt_lat: 259:0: latency 2446318
wbt_stat: 259:0: rmean=2446318, rmin=2446318, rmax=2446318, rsamples=1,
wmean=518866, wmin=15522, wmax=5330353, wsamples=57
wbt_step: 259:0: step down: step=1, window=72727272, background=8, normal=16, max=32
This shows a sync issue event (wbt_lat) that exceeded it's time. wbt_stat
dumps the current read/write stats for that window, and wbt_step shows a
step down event where we now scale back writes. Each trace includes the
device, 259:0 in this case.
Signed-off-by: Jens Axboe <axboe@fb.com>
2016-11-09 20:36:15 +01:00
|
|
|
|
|
|
|
#endif /* CONFIG_BLK_WBT */
|
|
|
|
|
|
|
|
#endif
|