xref: /openbmc/linux/drivers/md/bcache/writeback.h (revision 82e6fdd6)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHE_WRITEBACK_H
3 #define _BCACHE_WRITEBACK_H
4 
5 #define CUTOFF_WRITEBACK	40
6 #define CUTOFF_WRITEBACK_SYNC	70
7 
8 #define MAX_WRITEBACKS_IN_PASS  5
9 #define MAX_WRITESIZE_IN_PASS   5000	/* *512b */
10 
11 #define WRITEBACK_RATE_UPDATE_SECS_MAX		60
12 #define WRITEBACK_RATE_UPDATE_SECS_DEFAULT	5
13 
14 /*
15  * 14 (16384ths) is chosen here as something that each backing device
16  * should be a reasonable fraction of the share, and not to blow up
17  * until individual backing devices are a petabyte.
18  */
19 #define WRITEBACK_SHARE_SHIFT   14
20 
21 static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
22 {
23 	uint64_t i, ret = 0;
24 
25 	for (i = 0; i < d->nr_stripes; i++)
26 		ret += atomic_read(d->stripe_sectors_dirty + i);
27 
28 	return ret;
29 }
30 
31 static inline uint64_t  bcache_flash_devs_sectors_dirty(struct cache_set *c)
32 {
33 	uint64_t i, ret = 0;
34 
35 	mutex_lock(&bch_register_lock);
36 
37 	for (i = 0; i < c->devices_max_used; i++) {
38 		struct bcache_device *d = c->devices[i];
39 
40 		if (!d || !UUID_FLASH_ONLY(&c->uuids[i]))
41 			continue;
42 	   ret += bcache_dev_sectors_dirty(d);
43 	}
44 
45 	mutex_unlock(&bch_register_lock);
46 
47 	return ret;
48 }
49 
50 static inline unsigned offset_to_stripe(struct bcache_device *d,
51 					uint64_t offset)
52 {
53 	do_div(offset, d->stripe_size);
54 	return offset;
55 }
56 
57 static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
58 					   uint64_t offset,
59 					   unsigned nr_sectors)
60 {
61 	unsigned stripe = offset_to_stripe(&dc->disk, offset);
62 
63 	while (1) {
64 		if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))
65 			return true;
66 
67 		if (nr_sectors <= dc->disk.stripe_size)
68 			return false;
69 
70 		nr_sectors -= dc->disk.stripe_size;
71 		stripe++;
72 	}
73 }
74 
75 static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
76 				    unsigned cache_mode, bool would_skip)
77 {
78 	unsigned in_use = dc->disk.c->gc_stats.in_use;
79 
80 	if (cache_mode != CACHE_MODE_WRITEBACK ||
81 	    test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
82 	    in_use > CUTOFF_WRITEBACK_SYNC)
83 		return false;
84 
85 	if (dc->partial_stripes_expensive &&
86 	    bcache_dev_stripe_dirty(dc, bio->bi_iter.bi_sector,
87 				    bio_sectors(bio)))
88 		return true;
89 
90 	if (would_skip)
91 		return false;
92 
93 	return (op_is_sync(bio->bi_opf) ||
94 		bio->bi_opf & (REQ_META|REQ_PRIO) ||
95 		in_use <= CUTOFF_WRITEBACK);
96 }
97 
98 static inline void bch_writeback_queue(struct cached_dev *dc)
99 {
100 	if (!IS_ERR_OR_NULL(dc->writeback_thread))
101 		wake_up_process(dc->writeback_thread);
102 }
103 
104 static inline void bch_writeback_add(struct cached_dev *dc)
105 {
106 	if (!atomic_read(&dc->has_dirty) &&
107 	    !atomic_xchg(&dc->has_dirty, 1)) {
108 		refcount_inc(&dc->count);
109 
110 		if (BDEV_STATE(&dc->sb) != BDEV_STATE_DIRTY) {
111 			SET_BDEV_STATE(&dc->sb, BDEV_STATE_DIRTY);
112 			/* XXX: should do this synchronously */
113 			bch_write_bdev_super(dc, NULL);
114 		}
115 
116 		bch_writeback_queue(dc);
117 	}
118 }
119 
120 void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
121 
122 void bch_sectors_dirty_init(struct bcache_device *);
123 void bch_cached_dev_writeback_init(struct cached_dev *);
124 int bch_cached_dev_writeback_start(struct cached_dev *);
125 
126 #endif
127