LCOV - code coverage report
Current view: top level - dm-pcache - cache_writeback.c (source / functions) Coverage Total Hit
Test: dm_pcache.info Lines: 90.0 % 160 144
Test Date: 2025-08-04 03:13:17 Functions: 100.0 % 10 10
Legend: Lines: hit not hit

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

Generated by: LCOV version 2.0-1