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