xref: /linux/drivers/md/dm-pcache/cache_writeback.c (revision 4f38da1f027ea2c9f01bb71daa7a299c191b6940)
1*1d57628fSDongsheng Yang // SPDX-License-Identifier: GPL-2.0-or-later
2*1d57628fSDongsheng Yang 
3*1d57628fSDongsheng Yang #include <linux/bio.h>
4*1d57628fSDongsheng Yang 
5*1d57628fSDongsheng Yang #include "cache.h"
6*1d57628fSDongsheng Yang #include "backing_dev.h"
7*1d57628fSDongsheng Yang #include "cache_dev.h"
8*1d57628fSDongsheng Yang #include "dm_pcache.h"
9*1d57628fSDongsheng Yang 
10*1d57628fSDongsheng Yang static void writeback_ctx_end(struct pcache_cache *cache, int ret)
11*1d57628fSDongsheng Yang {
12*1d57628fSDongsheng Yang 	if (ret && !cache->writeback_ctx.ret) {
13*1d57628fSDongsheng Yang 		pcache_dev_err(CACHE_TO_PCACHE(cache), "writeback error: %d", ret);
14*1d57628fSDongsheng Yang 		cache->writeback_ctx.ret = ret;
15*1d57628fSDongsheng Yang 	}
16*1d57628fSDongsheng Yang 
17*1d57628fSDongsheng Yang 	if (!atomic_dec_and_test(&cache->writeback_ctx.pending))
18*1d57628fSDongsheng Yang 		return;
19*1d57628fSDongsheng Yang 
20*1d57628fSDongsheng Yang 	if (!cache->writeback_ctx.ret) {
21*1d57628fSDongsheng Yang 		backing_dev_flush(cache->backing_dev);
22*1d57628fSDongsheng Yang 
23*1d57628fSDongsheng Yang 		mutex_lock(&cache->dirty_tail_lock);
24*1d57628fSDongsheng Yang 		cache_pos_advance(&cache->dirty_tail, cache->writeback_ctx.advance);
25*1d57628fSDongsheng Yang 		cache_encode_dirty_tail(cache);
26*1d57628fSDongsheng Yang 		mutex_unlock(&cache->dirty_tail_lock);
27*1d57628fSDongsheng Yang 	}
28*1d57628fSDongsheng Yang 	queue_delayed_work(cache_get_wq(cache), &cache->writeback_work, 0);
29*1d57628fSDongsheng Yang }
30*1d57628fSDongsheng Yang 
31*1d57628fSDongsheng Yang static void writeback_end_req(struct pcache_backing_dev_req *backing_req, int ret)
32*1d57628fSDongsheng Yang {
33*1d57628fSDongsheng Yang 	struct pcache_cache *cache = backing_req->priv_data;
34*1d57628fSDongsheng Yang 
35*1d57628fSDongsheng Yang 	mutex_lock(&cache->writeback_lock);
36*1d57628fSDongsheng Yang 	writeback_ctx_end(cache, ret);
37*1d57628fSDongsheng Yang 	mutex_unlock(&cache->writeback_lock);
38*1d57628fSDongsheng Yang }
39*1d57628fSDongsheng Yang 
40*1d57628fSDongsheng Yang static inline bool is_cache_clean(struct pcache_cache *cache, struct pcache_cache_pos *dirty_tail)
41*1d57628fSDongsheng Yang {
42*1d57628fSDongsheng Yang 	struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
43*1d57628fSDongsheng Yang 	struct pcache_cache_kset_onmedia *kset_onmedia;
44*1d57628fSDongsheng Yang 	u32 to_copy;
45*1d57628fSDongsheng Yang 	void *addr;
46*1d57628fSDongsheng Yang 	int ret;
47*1d57628fSDongsheng Yang 
48*1d57628fSDongsheng Yang 	addr = cache_pos_addr(dirty_tail);
49*1d57628fSDongsheng Yang 	kset_onmedia = (struct pcache_cache_kset_onmedia *)cache->wb_kset_onmedia_buf;
50*1d57628fSDongsheng Yang 
51*1d57628fSDongsheng Yang 	to_copy = min(PCACHE_KSET_ONMEDIA_SIZE_MAX, PCACHE_SEG_SIZE - dirty_tail->seg_off);
52*1d57628fSDongsheng Yang 	ret = copy_mc_to_kernel(kset_onmedia, addr, to_copy);
53*1d57628fSDongsheng Yang 	if (ret) {
54*1d57628fSDongsheng Yang 		pcache_dev_err(pcache, "error to read kset: %d", ret);
55*1d57628fSDongsheng Yang 		return true;
56*1d57628fSDongsheng Yang 	}
57*1d57628fSDongsheng Yang 
58*1d57628fSDongsheng Yang 	/* Check if the magic number matches the expected value */
59*1d57628fSDongsheng Yang 	if (kset_onmedia->magic != PCACHE_KSET_MAGIC) {
60*1d57628fSDongsheng Yang 		pcache_dev_debug(pcache, "dirty_tail: %u:%u magic: %llx, not expected: %llx\n",
61*1d57628fSDongsheng Yang 				dirty_tail->cache_seg->cache_seg_id, dirty_tail->seg_off,
62*1d57628fSDongsheng Yang 				kset_onmedia->magic, PCACHE_KSET_MAGIC);
63*1d57628fSDongsheng Yang 		return true;
64*1d57628fSDongsheng Yang 	}
65*1d57628fSDongsheng Yang 
66*1d57628fSDongsheng Yang 	/* Verify the CRC checksum for data integrity */
67*1d57628fSDongsheng Yang 	if (kset_onmedia->crc != cache_kset_crc(kset_onmedia)) {
68*1d57628fSDongsheng Yang 		pcache_dev_debug(pcache, "dirty_tail: %u:%u crc: %x, not expected: %x\n",
69*1d57628fSDongsheng Yang 				dirty_tail->cache_seg->cache_seg_id, dirty_tail->seg_off,
70*1d57628fSDongsheng Yang 				cache_kset_crc(kset_onmedia), kset_onmedia->crc);
71*1d57628fSDongsheng Yang 		return true;
72*1d57628fSDongsheng Yang 	}
73*1d57628fSDongsheng Yang 
74*1d57628fSDongsheng Yang 	return false;
75*1d57628fSDongsheng Yang }
76*1d57628fSDongsheng Yang 
77*1d57628fSDongsheng Yang void cache_writeback_exit(struct pcache_cache *cache)
78*1d57628fSDongsheng Yang {
79*1d57628fSDongsheng Yang 	cancel_delayed_work_sync(&cache->writeback_work);
80*1d57628fSDongsheng Yang 	backing_dev_flush(cache->backing_dev);
81*1d57628fSDongsheng Yang 	cache_tree_exit(&cache->writeback_key_tree);
82*1d57628fSDongsheng Yang }
83*1d57628fSDongsheng Yang 
84*1d57628fSDongsheng Yang int cache_writeback_init(struct pcache_cache *cache)
85*1d57628fSDongsheng Yang {
86*1d57628fSDongsheng Yang 	int ret;
87*1d57628fSDongsheng Yang 
88*1d57628fSDongsheng Yang 	ret = cache_tree_init(cache, &cache->writeback_key_tree, 1);
89*1d57628fSDongsheng Yang 	if (ret)
90*1d57628fSDongsheng Yang 		goto err;
91*1d57628fSDongsheng Yang 
92*1d57628fSDongsheng Yang 	atomic_set(&cache->writeback_ctx.pending, 0);
93*1d57628fSDongsheng Yang 
94*1d57628fSDongsheng Yang 	/* Queue delayed work to start writeback handling */
95*1d57628fSDongsheng Yang 	queue_delayed_work(cache_get_wq(cache), &cache->writeback_work, 0);
96*1d57628fSDongsheng Yang 
97*1d57628fSDongsheng Yang 	return 0;
98*1d57628fSDongsheng Yang err:
99*1d57628fSDongsheng Yang 	return ret;
100*1d57628fSDongsheng Yang }
101*1d57628fSDongsheng Yang 
102*1d57628fSDongsheng Yang static void cache_key_writeback(struct pcache_cache *cache, struct pcache_cache_key *key)
103*1d57628fSDongsheng Yang {
104*1d57628fSDongsheng Yang 	struct pcache_backing_dev_req *writeback_req;
105*1d57628fSDongsheng Yang 	struct pcache_backing_dev_req_opts writeback_req_opts = { 0 };
106*1d57628fSDongsheng Yang 	struct pcache_cache_pos *pos;
107*1d57628fSDongsheng Yang 	void *addr;
108*1d57628fSDongsheng Yang 	u32 seg_remain, req_len, done = 0;
109*1d57628fSDongsheng Yang 
110*1d57628fSDongsheng Yang 	if (cache_key_clean(key))
111*1d57628fSDongsheng Yang 		return;
112*1d57628fSDongsheng Yang 
113*1d57628fSDongsheng Yang 	pos = &key->cache_pos;
114*1d57628fSDongsheng Yang 
115*1d57628fSDongsheng Yang 	seg_remain = cache_seg_remain(pos);
116*1d57628fSDongsheng Yang 	BUG_ON(seg_remain < key->len);
117*1d57628fSDongsheng Yang next_req:
118*1d57628fSDongsheng Yang 	addr = cache_pos_addr(pos) + done;
119*1d57628fSDongsheng Yang 	req_len = backing_dev_req_coalesced_max_len(addr, key->len - done);
120*1d57628fSDongsheng Yang 
121*1d57628fSDongsheng Yang 	writeback_req_opts.type = BACKING_DEV_REQ_TYPE_KMEM;
122*1d57628fSDongsheng Yang 	writeback_req_opts.gfp_mask = GFP_NOIO;
123*1d57628fSDongsheng Yang 	writeback_req_opts.end_fn = writeback_end_req;
124*1d57628fSDongsheng Yang 	writeback_req_opts.priv_data = cache;
125*1d57628fSDongsheng Yang 
126*1d57628fSDongsheng Yang 	writeback_req_opts.kmem.data = addr;
127*1d57628fSDongsheng Yang 	writeback_req_opts.kmem.opf = REQ_OP_WRITE;
128*1d57628fSDongsheng Yang 	writeback_req_opts.kmem.len = req_len;
129*1d57628fSDongsheng Yang 	writeback_req_opts.kmem.backing_off = key->off + done;
130*1d57628fSDongsheng Yang 
131*1d57628fSDongsheng Yang 	writeback_req = backing_dev_req_create(cache->backing_dev, &writeback_req_opts);
132*1d57628fSDongsheng Yang 
133*1d57628fSDongsheng Yang 	atomic_inc(&cache->writeback_ctx.pending);
134*1d57628fSDongsheng Yang 	backing_dev_req_submit(writeback_req, true);
135*1d57628fSDongsheng Yang 
136*1d57628fSDongsheng Yang 	done += req_len;
137*1d57628fSDongsheng Yang 	if (done < key->len)
138*1d57628fSDongsheng Yang 		goto next_req;
139*1d57628fSDongsheng Yang }
140*1d57628fSDongsheng Yang 
141*1d57628fSDongsheng Yang static void cache_wb_tree_writeback(struct pcache_cache *cache, u32 advance)
142*1d57628fSDongsheng Yang {
143*1d57628fSDongsheng Yang 	struct pcache_cache_tree *cache_tree = &cache->writeback_key_tree;
144*1d57628fSDongsheng Yang 	struct pcache_cache_subtree *cache_subtree;
145*1d57628fSDongsheng Yang 	struct rb_node *node;
146*1d57628fSDongsheng Yang 	struct pcache_cache_key *key;
147*1d57628fSDongsheng Yang 	u32 i;
148*1d57628fSDongsheng Yang 
149*1d57628fSDongsheng Yang 	cache->writeback_ctx.ret = 0;
150*1d57628fSDongsheng Yang 	cache->writeback_ctx.advance = advance;
151*1d57628fSDongsheng Yang 	atomic_set(&cache->writeback_ctx.pending, 1);
152*1d57628fSDongsheng Yang 
153*1d57628fSDongsheng Yang 	for (i = 0; i < cache_tree->n_subtrees; i++) {
154*1d57628fSDongsheng Yang 		cache_subtree = &cache_tree->subtrees[i];
155*1d57628fSDongsheng Yang 
156*1d57628fSDongsheng Yang 		node = rb_first(&cache_subtree->root);
157*1d57628fSDongsheng Yang 		while (node) {
158*1d57628fSDongsheng Yang 			key = CACHE_KEY(node);
159*1d57628fSDongsheng Yang 			node = rb_next(node);
160*1d57628fSDongsheng Yang 
161*1d57628fSDongsheng Yang 			cache_key_writeback(cache, key);
162*1d57628fSDongsheng Yang 			cache_key_delete(key);
163*1d57628fSDongsheng Yang 		}
164*1d57628fSDongsheng Yang 	}
165*1d57628fSDongsheng Yang 	writeback_ctx_end(cache, 0);
166*1d57628fSDongsheng Yang }
167*1d57628fSDongsheng Yang 
168*1d57628fSDongsheng Yang static int cache_kset_insert_tree(struct pcache_cache *cache, struct pcache_cache_kset_onmedia *kset_onmedia)
169*1d57628fSDongsheng Yang {
170*1d57628fSDongsheng Yang 	struct pcache_cache_key_onmedia *key_onmedia;
171*1d57628fSDongsheng Yang 	struct pcache_cache_subtree *cache_subtree;
172*1d57628fSDongsheng Yang 	struct pcache_cache_key *key;
173*1d57628fSDongsheng Yang 	int ret;
174*1d57628fSDongsheng Yang 	u32 i;
175*1d57628fSDongsheng Yang 
176*1d57628fSDongsheng Yang 	/* Iterate through all keys in the kset and write each back to storage */
177*1d57628fSDongsheng Yang 	for (i = 0; i < kset_onmedia->key_num; i++) {
178*1d57628fSDongsheng Yang 		key_onmedia = &kset_onmedia->data[i];
179*1d57628fSDongsheng Yang 
180*1d57628fSDongsheng Yang 		key = cache_key_alloc(&cache->writeback_key_tree, GFP_NOIO);
181*1d57628fSDongsheng Yang 		ret = cache_key_decode(cache, key_onmedia, key);
182*1d57628fSDongsheng Yang 		if (ret) {
183*1d57628fSDongsheng Yang 			cache_key_put(key);
184*1d57628fSDongsheng Yang 			goto clear_tree;
185*1d57628fSDongsheng Yang 		}
186*1d57628fSDongsheng Yang 
187*1d57628fSDongsheng Yang 		cache_subtree = get_subtree(&cache->writeback_key_tree, key->off);
188*1d57628fSDongsheng Yang 		spin_lock(&cache_subtree->tree_lock);
189*1d57628fSDongsheng Yang 		cache_key_insert(&cache->writeback_key_tree, key, true);
190*1d57628fSDongsheng Yang 		spin_unlock(&cache_subtree->tree_lock);
191*1d57628fSDongsheng Yang 	}
192*1d57628fSDongsheng Yang 
193*1d57628fSDongsheng Yang 	return 0;
194*1d57628fSDongsheng Yang clear_tree:
195*1d57628fSDongsheng Yang 	cache_tree_clear(&cache->writeback_key_tree);
196*1d57628fSDongsheng Yang 	return ret;
197*1d57628fSDongsheng Yang }
198*1d57628fSDongsheng Yang 
199*1d57628fSDongsheng Yang static void last_kset_writeback(struct pcache_cache *cache,
200*1d57628fSDongsheng Yang 		struct pcache_cache_kset_onmedia *last_kset_onmedia)
201*1d57628fSDongsheng Yang {
202*1d57628fSDongsheng Yang 	struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
203*1d57628fSDongsheng Yang 	struct pcache_cache_segment *next_seg;
204*1d57628fSDongsheng Yang 
205*1d57628fSDongsheng Yang 	pcache_dev_debug(pcache, "last kset, next: %u\n", last_kset_onmedia->next_cache_seg_id);
206*1d57628fSDongsheng Yang 
207*1d57628fSDongsheng Yang 	next_seg = &cache->segments[last_kset_onmedia->next_cache_seg_id];
208*1d57628fSDongsheng Yang 
209*1d57628fSDongsheng Yang 	mutex_lock(&cache->dirty_tail_lock);
210*1d57628fSDongsheng Yang 	cache->dirty_tail.cache_seg = next_seg;
211*1d57628fSDongsheng Yang 	cache->dirty_tail.seg_off = 0;
212*1d57628fSDongsheng Yang 	cache_encode_dirty_tail(cache);
213*1d57628fSDongsheng Yang 	mutex_unlock(&cache->dirty_tail_lock);
214*1d57628fSDongsheng Yang }
215*1d57628fSDongsheng Yang 
216*1d57628fSDongsheng Yang void cache_writeback_fn(struct work_struct *work)
217*1d57628fSDongsheng Yang {
218*1d57628fSDongsheng Yang 	struct pcache_cache *cache = container_of(work, struct pcache_cache, writeback_work.work);
219*1d57628fSDongsheng Yang 	struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
220*1d57628fSDongsheng Yang 	struct pcache_cache_pos dirty_tail;
221*1d57628fSDongsheng Yang 	struct pcache_cache_kset_onmedia *kset_onmedia;
222*1d57628fSDongsheng Yang 	u32 delay;
223*1d57628fSDongsheng Yang 	int ret;
224*1d57628fSDongsheng Yang 
225*1d57628fSDongsheng Yang 	mutex_lock(&cache->writeback_lock);
226*1d57628fSDongsheng Yang 	if (atomic_read(&cache->writeback_ctx.pending))
227*1d57628fSDongsheng Yang 		goto unlock;
228*1d57628fSDongsheng Yang 
229*1d57628fSDongsheng Yang 	if (pcache_is_stopping(pcache))
230*1d57628fSDongsheng Yang 		goto unlock;
231*1d57628fSDongsheng Yang 
232*1d57628fSDongsheng Yang 	kset_onmedia = (struct pcache_cache_kset_onmedia *)cache->wb_kset_onmedia_buf;
233*1d57628fSDongsheng Yang 
234*1d57628fSDongsheng Yang 	mutex_lock(&cache->dirty_tail_lock);
235*1d57628fSDongsheng Yang 	cache_pos_copy(&dirty_tail, &cache->dirty_tail);
236*1d57628fSDongsheng Yang 	mutex_unlock(&cache->dirty_tail_lock);
237*1d57628fSDongsheng Yang 
238*1d57628fSDongsheng Yang 	if (is_cache_clean(cache, &dirty_tail)) {
239*1d57628fSDongsheng Yang 		delay = PCACHE_CACHE_WRITEBACK_INTERVAL;
240*1d57628fSDongsheng Yang 		goto queue_work;
241*1d57628fSDongsheng Yang 	}
242*1d57628fSDongsheng Yang 
243*1d57628fSDongsheng Yang 	if (kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST) {
244*1d57628fSDongsheng Yang 		last_kset_writeback(cache, kset_onmedia);
245*1d57628fSDongsheng Yang 		delay = 0;
246*1d57628fSDongsheng Yang 		goto queue_work;
247*1d57628fSDongsheng Yang 	}
248*1d57628fSDongsheng Yang 
249*1d57628fSDongsheng Yang 	ret = cache_kset_insert_tree(cache, kset_onmedia);
250*1d57628fSDongsheng Yang 	if (ret) {
251*1d57628fSDongsheng Yang 		delay = PCACHE_CACHE_WRITEBACK_INTERVAL;
252*1d57628fSDongsheng Yang 		goto queue_work;
253*1d57628fSDongsheng Yang 	}
254*1d57628fSDongsheng Yang 
255*1d57628fSDongsheng Yang 	cache_wb_tree_writeback(cache, get_kset_onmedia_size(kset_onmedia));
256*1d57628fSDongsheng Yang 	delay = 0;
257*1d57628fSDongsheng Yang queue_work:
258*1d57628fSDongsheng Yang 	queue_delayed_work(cache_get_wq(cache), &cache->writeback_work, delay);
259*1d57628fSDongsheng Yang unlock:
260*1d57628fSDongsheng Yang 	mutex_unlock(&cache->writeback_lock);
261*1d57628fSDongsheng Yang }
262