blk-wbt.h 3.0 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3 4 5 6 7 8 9 10 11
#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"
12
#include "blk-rq-qos.h"
13 14 15 16 17

enum wbt_flags {
	WBT_TRACKED		= 1,	/* write, tracked for throttling */
	WBT_READ		= 2,	/* read */
	WBT_KSWAPD		= 4,	/* write, from kswapd */
18
	WBT_DISCARD		= 8,	/* discard */
19

20
	WBT_NR_BITS		= 4,	/* number of bits */
21 22 23
};

enum {
24 25
	WBT_RWQ_BG		= 0,
	WBT_RWQ_KSWAPD,
26
	WBT_RWQ_DISCARD,
27
	WBT_NUM_RWQ,
28 29
};

30
/*
Y
Yu Kuai 已提交
31 32 33
 * If current state is WBT_STATE_ON/OFF_DEFAULT, it can be covered to any other
 * state, if current state is WBT_STATE_ON/OFF_MANUAL, it can only be covered
 * to WBT_STATE_OFF/ON_MANUAL.
34 35
 */
enum {
Y
Yu Kuai 已提交
36 37 38 39
	WBT_STATE_ON_DEFAULT	= 1,	/* on by default */
	WBT_STATE_ON_MANUAL	= 2,	/* on manually by sysfs */
	WBT_STATE_OFF_DEFAULT	= 3,	/* off by default */
	WBT_STATE_OFF_MANUAL	= 4,	/* off manually by sysfs */
40 41
};

42 43 44 45 46 47 48
struct rq_wb {
	/*
	 * Settings that govern how we throttle
	 */
	unsigned int wb_background;		/* background writeback */
	unsigned int wb_normal;			/* normal writeback */

49 50
	short enable_state;			/* WBT_STATE_* */

51 52 53 54 55 56 57 58 59
	/*
	 * 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 */

60
	struct blk_stat_callback *cb;
61

62
	u64 sync_issue;
63 64 65 66 67 68 69
	void *sync_cookie;

	unsigned int wc;

	unsigned long last_issue;		/* last non-throttled issue */
	unsigned long last_comp;		/* last non-throttled comp */
	unsigned long min_lat_nsec;
70
	struct rq_qos rqos;
71
	struct rq_wait rq_wait[WBT_NUM_RWQ];
72
	struct rq_depth rq_depth;
73 74
};

75 76 77 78 79
static inline struct rq_wb *RQWB(struct rq_qos *rqos)
{
	return container_of(rqos, struct rq_wb, rqos);
}

80 81 82 83 84 85 86 87 88 89
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;
}

90

91 92
#ifdef CONFIG_BLK_WBT

J
Jens Axboe 已提交
93
int wbt_init(struct request_queue *);
94
void wbt_disable_default(struct request_queue *);
95
void wbt_enable_default(struct request_queue *);
96

97 98
u64 wbt_get_min_lat(struct request_queue *q);
void wbt_set_min_lat(struct request_queue *q, u64 val);
99
bool wbt_disabled(struct request_queue *);
100 101

void wbt_set_write_cache(struct request_queue *, bool);
102

103 104
u64 wbt_default_latency_nsec(struct request_queue *);

105 106
#else

J
Jens Axboe 已提交
107
static inline int wbt_init(struct request_queue *q)
108 109 110
{
	return -EINVAL;
}
111
static inline void wbt_disable_default(struct request_queue *q)
112 113
{
}
114
static inline void wbt_enable_default(struct request_queue *q)
115 116
{
}
117
static inline void wbt_set_write_cache(struct request_queue *q, bool wc)
118 119
{
}
120
static inline u64 wbt_get_min_lat(struct request_queue *q)
121
{
122
	return 0;
123
}
124
static inline void wbt_set_min_lat(struct request_queue *q, u64 val)
125 126
{
}
127 128 129 130
static inline u64 wbt_default_latency_nsec(struct request_queue *q)
{
	return 0;
}
131 132 133 134
static inline bool wbt_disabled(struct request_queue *q)
{
	return true;
}
135 136 137 138

#endif /* CONFIG_BLK_WBT */

#endif