LCOV - code coverage report
Current view: top level - dm-pcache - cache.c (source / functions) Coverage Total Hit
Test: dm_pcache.info Lines: 85.5 % 249 213
Test Date: 2025-08-08 02:43:50 Functions: 100.0 % 18 18
Legend: Lines: hit not hit

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-or-later
       2              : #include <linux/blk_types.h>
       3              : 
       4              : #include "cache.h"
       5              : #include "cache_dev.h"
       6              : #include "backing_dev.h"
       7              : #include "dm_pcache.h"
       8              : 
       9              : struct kmem_cache *key_cache;
      10              : 
      11          232 : static inline struct pcache_cache_info *get_cache_info_addr(struct pcache_cache *cache)
      12              : {
      13          232 :         return cache->cache_info_addr + cache->info_index;
      14              : }
      15              : 
      16          232 : static void cache_info_write(struct pcache_cache *cache)
      17              : {
      18          232 :         struct pcache_cache_info *cache_info = &cache->cache_info;
      19              : 
      20          232 :         cache_info->header.seq++;
      21          232 :         cache_info->header.crc = pcache_meta_crc(&cache_info->header,
      22              :                                                 sizeof(struct pcache_cache_info));
      23              : 
      24          232 :         memcpy_flushcache(get_cache_info_addr(cache), cache_info,
      25              :                         sizeof(struct pcache_cache_info));
      26              : 
      27          232 :         cache->info_index = (cache->info_index + 1) % PCACHE_META_INDEX_MAX;
      28          232 : }
      29              : 
      30              : static void cache_info_init_default(struct pcache_cache *cache);
      31          197 : static int cache_info_init(struct pcache_cache *cache, struct pcache_cache_options *opts)
      32              : {
      33          197 :         struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
      34          197 :         struct pcache_cache_info *cache_info_addr;
      35              : 
      36          394 :         cache_info_addr = pcache_meta_find_latest(&cache->cache_info_addr->header,
      37              :                                                 sizeof(struct pcache_cache_info),
      38              :                                                 PCACHE_CACHE_INFO_SIZE,
      39          197 :                                                 &cache->cache_info);
      40          197 :         if (IS_ERR(cache_info_addr))
      41            0 :                 return PTR_ERR(cache_info_addr);
      42              : 
      43          197 :         if (cache_info_addr) {
      44           66 :                 if (opts->data_crc !=
      45           66 :                                 (cache->cache_info.flags & PCACHE_CACHE_FLAGS_DATA_CRC)) {
      46            5 :                         pcache_dev_err(pcache, "invalid option for data_crc: %s, expected: %s",
      47              :                                         opts->data_crc ? "true" : "false",
      48              :                                         cache->cache_info.flags & PCACHE_CACHE_FLAGS_DATA_CRC ? "true" : "false");
      49            3 :                         return -EINVAL;
      50              :                 }
      51              : 
      52              :                 return 0;
      53              :         }
      54              : 
      55              :         /* init cache_info for new cache */
      56          131 :         cache_info_init_default(cache);
      57          131 :         cache_mode_set(cache, opts->cache_mode);
      58          131 :         if (opts->data_crc)
      59           69 :                 cache->cache_info.flags |= PCACHE_CACHE_FLAGS_DATA_CRC;
      60              : 
      61              :         return 0;
      62              : }
      63              : 
      64          169 : static void cache_info_set_gc_percent(struct pcache_cache_info *cache_info, u8 percent)
      65              : {
      66          169 :         cache_info->flags &= ~PCACHE_CACHE_FLAGS_GC_PERCENT_MASK;
      67           38 :         cache_info->flags |= FIELD_PREP(PCACHE_CACHE_FLAGS_GC_PERCENT_MASK, percent);
      68           38 : }
      69              : 
      70           40 : int pcache_cache_set_gc_percent(struct pcache_cache *cache, u8 percent)
      71              : {
      72           40 :         if (percent > PCACHE_CACHE_GC_PERCENT_MAX || percent < PCACHE_CACHE_GC_PERCENT_MIN)
      73              :                 return -EINVAL;
      74              : 
      75           38 :         mutex_lock(&cache->cache_info_lock);
      76           38 :         cache_info_set_gc_percent(&cache->cache_info, percent);
      77              : 
      78           38 :         cache_info_write(cache);
      79           38 :         mutex_unlock(&cache->cache_info_lock);
      80              : 
      81           38 :         return 0;
      82              : }
      83              : 
      84      5730773 : void cache_pos_encode(struct pcache_cache *cache,
      85              :                              struct pcache_cache_pos_onmedia *pos_onmedia_base,
      86              :                              struct pcache_cache_pos *pos, u64 seq, u32 *index)
      87              : {
      88      5730773 :         struct pcache_cache_pos_onmedia pos_onmedia;
      89      5730773 :         struct pcache_cache_pos_onmedia *pos_onmedia_addr = pos_onmedia_base + *index;
      90              : 
      91      5730773 :         pos_onmedia.cache_seg_id = pos->cache_seg->cache_seg_id;
      92      5730773 :         pos_onmedia.seg_off = pos->seg_off;
      93      5730773 :         pos_onmedia.header.seq = seq;
      94      5730773 :         pos_onmedia.header.crc = cache_pos_onmedia_crc(&pos_onmedia);
      95              : 
      96      5731363 :         memcpy_flushcache(pos_onmedia_addr, &pos_onmedia, sizeof(struct pcache_cache_pos_onmedia));
      97      5731363 :         pmem_wmb();
      98              : 
      99      5729084 :         *index = (*index + 1) % PCACHE_META_INDEX_MAX;
     100      5729084 : }
     101              : 
     102          126 : int cache_pos_decode(struct pcache_cache *cache,
     103              :                             struct pcache_cache_pos_onmedia *pos_onmedia,
     104              :                             struct pcache_cache_pos *pos, u64 *seq, u32 *index)
     105              : {
     106          126 :         struct pcache_cache_pos_onmedia latest, *latest_addr;
     107              : 
     108          126 :         latest_addr = pcache_meta_find_latest(&pos_onmedia->header,
     109              :                                         sizeof(struct pcache_cache_pos_onmedia),
     110              :                                         sizeof(struct pcache_cache_pos_onmedia),
     111              :                                         &latest);
     112          126 :         if (IS_ERR(latest_addr))
     113            0 :                 return PTR_ERR(latest_addr);
     114              : 
     115          126 :         if (!latest_addr)
     116              :                 return -EIO;
     117              : 
     118          126 :         pos->cache_seg = &cache->segments[latest.cache_seg_id];
     119          126 :         pos->seg_off = latest.seg_off;
     120          126 :         *seq = latest.header.seq;
     121          126 :         *index = (latest_addr - pos_onmedia);
     122              : 
     123          126 :         return 0;
     124              : }
     125              : 
     126          131 : static inline void cache_info_set_seg_id(struct pcache_cache *cache, u32 seg_id)
     127              : {
     128          131 :         cache->cache_info.seg_id = seg_id;
     129          131 : }
     130              : 
     131          197 : static int cache_init(struct dm_pcache *pcache)
     132              : {
     133          197 :         struct pcache_cache *cache = &pcache->cache;
     134          197 :         struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
     135          197 :         struct pcache_cache_dev *cache_dev = &pcache->cache_dev;
     136          197 :         int ret;
     137              : 
     138          197 :         cache->segments = kvcalloc(cache_dev->seg_num, sizeof(struct pcache_cache_segment), GFP_KERNEL);
     139          197 :         if (!cache->segments) {
     140            0 :                 ret = -ENOMEM;
     141            0 :                 goto err;
     142              :         }
     143              : 
     144          197 :         cache->seg_map = kvcalloc(BITS_TO_LONGS(cache_dev->seg_num), sizeof(unsigned long), GFP_KERNEL);
     145          197 :         if (!cache->seg_map) {
     146            0 :                 ret = -ENOMEM;
     147            0 :                 goto free_segments;
     148              :         }
     149              : 
     150          197 :         cache->backing_dev = backing_dev;
     151          197 :         cache->cache_dev = &pcache->cache_dev;
     152          197 :         cache->n_segs = cache_dev->seg_num;
     153          197 :         atomic_set(&cache->gc_errors, 0);
     154          197 :         spin_lock_init(&cache->seg_map_lock);
     155          197 :         spin_lock_init(&cache->key_head_lock);
     156              : 
     157          197 :         mutex_init(&cache->cache_info_lock);
     158          197 :         mutex_init(&cache->key_tail_lock);
     159          197 :         mutex_init(&cache->dirty_tail_lock);
     160          197 :         mutex_init(&cache->writeback_lock);
     161              : 
     162          197 :         INIT_DELAYED_WORK(&cache->writeback_work, cache_writeback_fn);
     163          197 :         INIT_DELAYED_WORK(&cache->gc_work, pcache_cache_gc_fn);
     164          197 :         INIT_WORK(&cache->clean_work, clean_fn);
     165              : 
     166          197 :         return 0;
     167              : 
     168            0 : free_segments:
     169            0 :         kvfree(cache->segments);
     170              : err:
     171              :         return ret;
     172              : }
     173              : 
     174          197 : static void cache_exit(struct pcache_cache *cache)
     175              : {
     176          197 :         kvfree(cache->seg_map);
     177          197 :         kvfree(cache->segments);
     178          197 : }
     179              : 
     180          131 : static void cache_info_init_default(struct pcache_cache *cache)
     181              : {
     182          131 :         struct pcache_cache_info *cache_info = &cache->cache_info;
     183              : 
     184          131 :         cache_info->header.seq = 0;
     185          131 :         cache_info->n_segs = cache->cache_dev->seg_num;
     186          131 :         cache_info_set_gc_percent(cache_info, PCACHE_CACHE_GC_PERCENT_DEFAULT);
     187              : }
     188              : 
     189          194 : static int cache_tail_init(struct pcache_cache *cache)
     190              : {
     191          194 :         struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
     192          194 :         bool new_cache = !(cache->cache_info.flags & PCACHE_CACHE_FLAGS_INIT_DONE);
     193              : 
     194          194 :         if (new_cache) {
     195          131 :                 __set_bit(0, cache->seg_map);
     196              : 
     197          131 :                 cache->key_head.cache_seg = &cache->segments[0];
     198          131 :                 cache->key_head.seg_off = 0;
     199          131 :                 cache_pos_copy(&cache->key_tail, &cache->key_head);
     200          131 :                 cache_pos_copy(&cache->dirty_tail, &cache->key_head);
     201              : 
     202          131 :                 cache_encode_dirty_tail(cache);
     203          131 :                 cache_encode_key_tail(cache);
     204              :         } else {
     205           63 :                 if (cache_decode_key_tail(cache) || cache_decode_dirty_tail(cache)) {
     206            0 :                         pcache_dev_err(pcache, "Corrupted key tail or dirty tail.\n");
     207            0 :                         return -EIO;
     208              :                 }
     209              :         }
     210              : 
     211              :         return 0;
     212              : }
     213              : 
     214        41790 : static int get_seg_id(struct pcache_cache *cache,
     215              :                       struct pcache_cache_segment *prev_cache_seg,
     216              :                       bool new_cache, u32 *seg_id)
     217              : {
     218        41790 :         struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
     219        41790 :         struct pcache_cache_dev *cache_dev = cache->cache_dev;
     220        41790 :         int ret;
     221              : 
     222        41790 :         if (new_cache) {
     223        30845 :                 ret = cache_dev_get_empty_segment_id(cache_dev, seg_id);
     224        30845 :                 if (ret) {
     225            0 :                         pcache_dev_err(pcache, "no available segment\n");
     226            0 :                         goto err;
     227              :                 }
     228              : 
     229        30845 :                 if (prev_cache_seg)
     230        30714 :                         cache_seg_set_next_seg(prev_cache_seg, *seg_id);
     231              :                 else
     232          131 :                         cache_info_set_seg_id(cache, *seg_id);
     233              :         } else {
     234        10945 :                 if (prev_cache_seg) {
     235        10882 :                         struct pcache_segment_info *prev_seg_info;
     236              : 
     237        10882 :                         prev_seg_info = &prev_cache_seg->cache_seg_info;
     238        10882 :                         if (!segment_info_has_next(prev_seg_info)) {
     239            0 :                                 ret = -EFAULT;
     240            0 :                                 goto err;
     241              :                         }
     242        10882 :                         *seg_id = prev_cache_seg->cache_seg_info.next_seg;
     243              :                 } else {
     244           63 :                         *seg_id = cache->cache_info.seg_id;
     245              :                 }
     246              :         }
     247              :         return 0;
     248              : err:
     249              :         return ret;
     250              : }
     251              : 
     252          194 : static int cache_segs_init(struct pcache_cache *cache)
     253              : {
     254          194 :         struct pcache_cache_segment *prev_cache_seg = NULL;
     255          194 :         struct pcache_cache_info *cache_info = &cache->cache_info;
     256          194 :         bool new_cache = !(cache->cache_info.flags & PCACHE_CACHE_FLAGS_INIT_DONE);
     257          194 :         u32 seg_id;
     258          194 :         int ret;
     259          194 :         u32 i;
     260              : 
     261        41984 :         for (i = 0; i < cache_info->n_segs; i++) {
     262        41790 :                 ret = get_seg_id(cache, prev_cache_seg, new_cache, &seg_id);
     263        41790 :                 if (ret)
     264            0 :                         goto err;
     265              : 
     266        41790 :                 ret = cache_seg_init(cache, seg_id, i, new_cache);
     267        41790 :                 if (ret)
     268            0 :                         goto err;
     269              : 
     270        41790 :                 prev_cache_seg = &cache->segments[i];
     271              :         }
     272              :         return 0;
     273              : err:
     274              :         return ret;
     275              : }
     276              : 
     277          194 : static int cache_init_req_keys(struct pcache_cache *cache, u32 n_paral)
     278              : {
     279          194 :         struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
     280          194 :         u32 n_subtrees;
     281          194 :         int ret;
     282          194 :         u32 i, cpu;
     283              : 
     284              :         /* Calculate number of cache trees based on the device size */
     285          194 :         n_subtrees = DIV_ROUND_UP(cache->dev_size << SECTOR_SHIFT, PCACHE_CACHE_SUBTREE_SIZE);
     286          194 :         ret = cache_tree_init(cache, &cache->req_key_tree, n_subtrees);
     287          194 :         if (ret)
     288            0 :                 goto err;
     289              : 
     290          194 :         cache->n_ksets = n_paral;
     291          194 :         cache->ksets = kvcalloc(cache->n_ksets, PCACHE_KSET_SIZE, GFP_KERNEL);
     292          194 :         if (!cache->ksets) {
     293            0 :                 ret = -ENOMEM;
     294            0 :                 goto req_tree_exit;
     295              :         }
     296              : 
     297              :         /*
     298              :          * Initialize each kset with a spinlock and delayed work for flushing.
     299              :          * Each kset is associated with one queue to ensure independent handling
     300              :          * of cache keys across multiple queues, maximizing multiqueue concurrency.
     301              :          */
     302        12610 :         for (i = 0; i < cache->n_ksets; i++) {
     303        12416 :                 struct pcache_cache_kset *kset = get_kset(cache, i);
     304              : 
     305        12416 :                 kset->cache = cache;
     306        12416 :                 spin_lock_init(&kset->kset_lock);
     307        12416 :                 INIT_DELAYED_WORK(&kset->flush_work, kset_flush_fn);
     308              :         }
     309              : 
     310          194 :         cache->data_heads = alloc_percpu(struct pcache_cache_data_head);
     311          194 :         if (!cache->data_heads) {
     312            0 :                 ret = -ENOMEM;
     313            0 :                 goto free_kset;
     314              :         }
     315              : 
     316        25220 :         for_each_possible_cpu(cpu) {
     317        24832 :                 struct pcache_cache_data_head *h =
     318        12416 :                         per_cpu_ptr(cache->data_heads, cpu);
     319        12416 :                 h->head_pos.cache_seg = NULL;
     320              :         }
     321              : 
     322              :         /*
     323              :          * Replay persisted cache keys using cache_replay.
     324              :          * This function loads and replays cache keys from previously stored
     325              :          * ksets, allowing the cache to restore its state after a restart.
     326              :          */
     327          194 :         ret = cache_replay(cache);
     328          194 :         if (ret) {
     329            0 :                 pcache_dev_err(pcache, "failed to replay keys\n");
     330            0 :                 goto free_heads;
     331              :         }
     332              : 
     333              :         return 0;
     334              : 
     335            0 : free_heads:
     336            0 :         free_percpu(cache->data_heads);
     337            0 : free_kset:
     338            0 :         kvfree(cache->ksets);
     339            0 : req_tree_exit:
     340            0 :         cache_tree_exit(&cache->req_key_tree);
     341              : err:
     342              :         return ret;
     343              : }
     344              : 
     345          194 : static void cache_destroy_req_keys(struct pcache_cache *cache)
     346              : {
     347          194 :         u32 i;
     348              : 
     349        12610 :         for (i = 0; i < cache->n_ksets; i++) {
     350        12416 :                 struct pcache_cache_kset *kset = get_kset(cache, i);
     351              : 
     352        12416 :                 cancel_delayed_work_sync(&kset->flush_work);
     353              :         }
     354              : 
     355          194 :         free_percpu(cache->data_heads);
     356          194 :         kvfree(cache->ksets);
     357          194 :         cache_tree_exit(&cache->req_key_tree);
     358          194 : }
     359              : 
     360          197 : int pcache_cache_start(struct dm_pcache *pcache)
     361              : {
     362          197 :         struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
     363          197 :         struct pcache_cache *cache = &pcache->cache;
     364          197 :         struct pcache_cache_options *opts = &pcache->opts;
     365          197 :         int ret;
     366              : 
     367          197 :         ret = cache_init(pcache);
     368          197 :         if (ret)
     369              :                 return ret;
     370              : 
     371          197 :         cache->cache_info_addr = CACHE_DEV_CACHE_INFO(cache->cache_dev);
     372          197 :         cache->cache_ctrl = CACHE_DEV_CACHE_CTRL(cache->cache_dev);
     373          197 :         backing_dev->cache = cache;
     374          197 :         cache->dev_size = backing_dev->dev_size;
     375              : 
     376          197 :         ret = cache_info_init(cache, opts);
     377          197 :         if (ret)
     378            3 :                 goto cache_exit;
     379              : 
     380          194 :         ret = cache_segs_init(cache);
     381          194 :         if (ret)
     382            0 :                 goto cache_exit;
     383              : 
     384          194 :         ret = cache_tail_init(cache);
     385          194 :         if (ret)
     386            0 :                 goto cache_exit;
     387              : 
     388          194 :         ret = cache_init_req_keys(cache, num_online_cpus());
     389          194 :         if (ret)
     390            0 :                 goto cache_exit;
     391              : 
     392          194 :         ret = cache_writeback_init(cache);
     393          194 :         if (ret)
     394            0 :                 goto destroy_keys;
     395              : 
     396          194 :         cache->cache_info.flags |= PCACHE_CACHE_FLAGS_INIT_DONE;
     397          194 :         cache_info_write(cache);
     398          194 :         queue_delayed_work(cache_get_wq(cache), &cache->gc_work, 0);
     399              : 
     400          194 :         return 0;
     401              : 
     402            0 : destroy_keys:
     403            0 :         cache_destroy_req_keys(cache);
     404            3 : cache_exit:
     405            3 :         cache_exit(cache);
     406              : 
     407            3 :         return ret;
     408              : }
     409              : 
     410          194 : void pcache_cache_stop(struct dm_pcache *pcache)
     411              : {
     412          194 :         struct pcache_cache *cache = &pcache->cache;
     413              : 
     414          194 :         cache_flush(cache);
     415              : 
     416          194 :         cancel_delayed_work_sync(&cache->gc_work);
     417          194 :         flush_work(&cache->clean_work);
     418          194 :         cache_writeback_exit(cache);
     419              : 
     420          194 :         if (cache->req_key_tree.n_subtrees)
     421          194 :                 cache_destroy_req_keys(cache);
     422              : 
     423          194 :         cache_exit(cache);
     424          194 : }
     425              : 
     426     28730275 : struct workqueue_struct *cache_get_wq(struct pcache_cache *cache)
     427              : {
     428     28730275 :         struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
     429              : 
     430          194 :         return pcache->task_wq;
     431              : }
     432              : 
     433          163 : int pcache_cache_init(void)
     434              : {
     435          163 :         key_cache = KMEM_CACHE(pcache_cache_key, 0);
     436          163 :         if (!key_cache)
     437            0 :                 return -ENOMEM;
     438              : 
     439              :         return 0;
     440              : }
     441              : 
     442           87 : void pcache_cache_exit(void)
     443              : {
     444           87 :         kmem_cache_destroy(key_cache);
     445           87 : }
        

Generated by: LCOV version 2.0-1