1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _BCACHE_WRITEBACK_H
3*4882a593Smuzhiyun #define _BCACHE_WRITEBACK_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #define CUTOFF_WRITEBACK 40
6*4882a593Smuzhiyun #define CUTOFF_WRITEBACK_SYNC 70
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #define CUTOFF_WRITEBACK_MAX 70
9*4882a593Smuzhiyun #define CUTOFF_WRITEBACK_SYNC_MAX 90
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define MAX_WRITEBACKS_IN_PASS 5
12*4882a593Smuzhiyun #define MAX_WRITESIZE_IN_PASS 5000 /* *512b */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define WRITEBACK_RATE_UPDATE_SECS_MAX 60
15*4882a593Smuzhiyun #define WRITEBACK_RATE_UPDATE_SECS_DEFAULT 5
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define BCH_AUTO_GC_DIRTY_THRESHOLD 50
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define BCH_DIRTY_INIT_THRD_MAX 12
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun * 14 (16384ths) is chosen here as something that each backing device
22*4882a593Smuzhiyun * should be a reasonable fraction of the share, and not to blow up
23*4882a593Smuzhiyun * until individual backing devices are a petabyte.
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun #define WRITEBACK_SHARE_SHIFT 14
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct bch_dirty_init_state;
28*4882a593Smuzhiyun struct dirty_init_thrd_info {
29*4882a593Smuzhiyun struct bch_dirty_init_state *state;
30*4882a593Smuzhiyun struct task_struct *thread;
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun struct bch_dirty_init_state {
34*4882a593Smuzhiyun struct cache_set *c;
35*4882a593Smuzhiyun struct bcache_device *d;
36*4882a593Smuzhiyun int total_threads;
37*4882a593Smuzhiyun int key_idx;
38*4882a593Smuzhiyun spinlock_t idx_lock;
39*4882a593Smuzhiyun atomic_t started;
40*4882a593Smuzhiyun atomic_t enough;
41*4882a593Smuzhiyun wait_queue_head_t wait;
42*4882a593Smuzhiyun struct dirty_init_thrd_info infos[BCH_DIRTY_INIT_THRD_MAX];
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun
bcache_dev_sectors_dirty(struct bcache_device * d)45*4882a593Smuzhiyun static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun uint64_t i, ret = 0;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun for (i = 0; i < d->nr_stripes; i++)
50*4882a593Smuzhiyun ret += atomic_read(d->stripe_sectors_dirty + i);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun return ret;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
offset_to_stripe(struct bcache_device * d,uint64_t offset)55*4882a593Smuzhiyun static inline int offset_to_stripe(struct bcache_device *d,
56*4882a593Smuzhiyun uint64_t offset)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun do_div(offset, d->stripe_size);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* d->nr_stripes is in range [1, INT_MAX] */
61*4882a593Smuzhiyun if (unlikely(offset >= d->nr_stripes)) {
62*4882a593Smuzhiyun pr_err("Invalid stripe %llu (>= nr_stripes %d).\n",
63*4882a593Smuzhiyun offset, d->nr_stripes);
64*4882a593Smuzhiyun return -EINVAL;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /*
68*4882a593Smuzhiyun * Here offset is definitly smaller than INT_MAX,
69*4882a593Smuzhiyun * return it as int will never overflow.
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun return offset;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
bcache_dev_stripe_dirty(struct cached_dev * dc,uint64_t offset,unsigned int nr_sectors)74*4882a593Smuzhiyun static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
75*4882a593Smuzhiyun uint64_t offset,
76*4882a593Smuzhiyun unsigned int nr_sectors)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun int stripe = offset_to_stripe(&dc->disk, offset);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (stripe < 0)
81*4882a593Smuzhiyun return false;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun while (1) {
84*4882a593Smuzhiyun if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))
85*4882a593Smuzhiyun return true;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if (nr_sectors <= dc->disk.stripe_size)
88*4882a593Smuzhiyun return false;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun nr_sectors -= dc->disk.stripe_size;
91*4882a593Smuzhiyun stripe++;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun extern unsigned int bch_cutoff_writeback;
96*4882a593Smuzhiyun extern unsigned int bch_cutoff_writeback_sync;
97*4882a593Smuzhiyun
should_writeback(struct cached_dev * dc,struct bio * bio,unsigned int cache_mode,bool would_skip)98*4882a593Smuzhiyun static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
99*4882a593Smuzhiyun unsigned int cache_mode, bool would_skip)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun unsigned int in_use = dc->disk.c->gc_stats.in_use;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if (cache_mode != CACHE_MODE_WRITEBACK ||
104*4882a593Smuzhiyun test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
105*4882a593Smuzhiyun in_use > bch_cutoff_writeback_sync)
106*4882a593Smuzhiyun return false;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (bio_op(bio) == REQ_OP_DISCARD)
109*4882a593Smuzhiyun return false;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (dc->partial_stripes_expensive &&
112*4882a593Smuzhiyun bcache_dev_stripe_dirty(dc, bio->bi_iter.bi_sector,
113*4882a593Smuzhiyun bio_sectors(bio)))
114*4882a593Smuzhiyun return true;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (would_skip)
117*4882a593Smuzhiyun return false;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun return (op_is_sync(bio->bi_opf) ||
120*4882a593Smuzhiyun bio->bi_opf & (REQ_META|REQ_PRIO) ||
121*4882a593Smuzhiyun in_use <= bch_cutoff_writeback);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
bch_writeback_queue(struct cached_dev * dc)124*4882a593Smuzhiyun static inline void bch_writeback_queue(struct cached_dev *dc)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(dc->writeback_thread))
127*4882a593Smuzhiyun wake_up_process(dc->writeback_thread);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
bch_writeback_add(struct cached_dev * dc)130*4882a593Smuzhiyun static inline void bch_writeback_add(struct cached_dev *dc)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun if (!atomic_read(&dc->has_dirty) &&
133*4882a593Smuzhiyun !atomic_xchg(&dc->has_dirty, 1)) {
134*4882a593Smuzhiyun if (BDEV_STATE(&dc->sb) != BDEV_STATE_DIRTY) {
135*4882a593Smuzhiyun SET_BDEV_STATE(&dc->sb, BDEV_STATE_DIRTY);
136*4882a593Smuzhiyun /* XXX: should do this synchronously */
137*4882a593Smuzhiyun bch_write_bdev_super(dc, NULL);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun bch_writeback_queue(dc);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned int inode,
145*4882a593Smuzhiyun uint64_t offset, int nr_sectors);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun void bch_sectors_dirty_init(struct bcache_device *d);
148*4882a593Smuzhiyun void bch_cached_dev_writeback_init(struct cached_dev *dc);
149*4882a593Smuzhiyun int bch_cached_dev_writeback_start(struct cached_dev *dc);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #endif
152