LCOV - code coverage report
Current view: top level - dm-pcache - pcache_internal.h (source / functions) Coverage Total Hit
Test: dm_pcache.info Lines: 82.6 % 23 19
Test Date: 2025-08-08 03:56:04 Functions: 100.0 % 1 1
Legend: Lines: hit not hit

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-2.0-or-later */
       2              : #ifndef _PCACHE_INTERNAL_H
       3              : #define _PCACHE_INTERNAL_H
       4              : 
       5              : #include <linux/delay.h>
       6              : #include <linux/crc32c.h>
       7              : 
       8              : #define pcache_err(fmt, ...)                                                    \
       9              :         pr_err("dm-pcache: %s:%u " fmt, __func__, __LINE__, ##__VA_ARGS__)
      10              : #define pcache_info(fmt, ...)                                                   \
      11              :         pr_info("dm-pcache: %s:%u " fmt, __func__, __LINE__, ##__VA_ARGS__)
      12              : #define pcache_debug(fmt, ...)                                                  \
      13              :         pr_debug("dm-pcache: %s:%u " fmt, __func__, __LINE__, ##__VA_ARGS__)
      14              : 
      15              : #define PCACHE_KB                       (1024ULL)
      16              : #define PCACHE_MB                       (1024 * PCACHE_KB)
      17              : 
      18              : /* Maximum number of metadata indices */
      19              : #define PCACHE_META_INDEX_MAX           2
      20              : 
      21              : #define PCACHE_CRC_SEED                 0x3B15A
      22              : /*
      23              :  * struct pcache_meta_header - PCACHE metadata header structure
      24              :  * @crc: CRC checksum for validating metadata integrity.
      25              :  * @seq: Sequence number to track metadata updates.
      26              :  * @version: Metadata version.
      27              :  * @res: Reserved space for future use.
      28              :  */
      29              : struct pcache_meta_header {
      30              :         __u32 crc;
      31              :         __u8  seq;
      32              :         __u8  version;
      33              :         __u16 res;
      34              : };
      35              : 
      36              : /*
      37              :  * pcache_meta_crc - Calculate CRC for the given metadata header.
      38              :  * @header: Pointer to the metadata header.
      39              :  * @meta_size: Size of the metadata structure.
      40              :  *
      41              :  * Returns the CRC checksum calculated by excluding the CRC field itself.
      42              :  */
      43     10429041 : static inline u32 pcache_meta_crc(struct pcache_meta_header *header, u32 meta_size)
      44              : {
      45     10299721 :         return crc32c(PCACHE_CRC_SEED, (void *)header + 4, meta_size - 4);
      46              : }
      47              : 
      48              : /*
      49              :  * pcache_meta_seq_after - Check if a sequence number is more recent, accounting for overflow.
      50              :  * @seq1: First sequence number.
      51              :  * @seq2: Second sequence number.
      52              :  *
      53              :  * Determines if @seq1 is more recent than @seq2 by calculating the signed
      54              :  * difference between them. This approach allows handling sequence number
      55              :  * overflow correctly because the difference wraps naturally, and any value
      56              :  * greater than zero indicates that @seq1 is "after" @seq2. This method
      57              :  * assumes 8-bit unsigned sequence numbers, where the difference wraps
      58              :  * around if seq1 overflows past seq2.
      59              :  *
      60              :  * Returns:
      61              :  *   - true if @seq1 is more recent than @seq2, indicating it comes "after"
      62              :  *   - false otherwise.
      63              :  */
      64        32758 : static inline bool pcache_meta_seq_after(u8 seq1, u8 seq2)
      65              : {
      66        32758 :         return (s8)(seq1 - seq2) > 0;
      67              : }
      68              : 
      69              : /*
      70              :  * pcache_meta_find_latest - Find the latest valid metadata.
      71              :  * @header: Pointer to the metadata header.
      72              :  * @meta_size: Size of each metadata block.
      73              :  *
      74              :  * Finds the latest valid metadata by checking sequence numbers. If a
      75              :  * valid entry with the highest sequence number is found, its pointer
      76              :  * is returned. Returns NULL if no valid metadata is found.
      77              :  */
      78        64660 : static inline void __must_check *pcache_meta_find_latest(struct pcache_meta_header *header,
      79              :                                         u32 meta_size, u32 meta_max_size,
      80              :                                         void *meta_ret)
      81              : {
      82        64660 :         struct pcache_meta_header *meta, *latest = NULL;
      83        64660 :         u32 i, seq_latest = 0;
      84        64660 :         void *meta_addr;
      85              : 
      86        64660 :         meta = meta_ret;
      87              : 
      88       193980 :         for (i = 0; i < PCACHE_META_INDEX_MAX; i++) {
      89       129320 :                 meta_addr = (void *)header + (i * meta_max_size);
      90       129320 :                 if (copy_mc_to_kernel(meta, meta_addr, meta_size)) {
      91            0 :                         pcache_err("hardware memory error when copy meta");
      92            0 :                         return ERR_PTR(-EIO);
      93              :                 }
      94              : 
      95              :                 /* Skip if CRC check fails, which means corrupted */
      96       129320 :                 if (meta->crc != pcache_meta_crc(meta, meta_size))
      97        32170 :                         continue;
      98              : 
      99              :                 /* Update latest if a more recent sequence is found */
     100        97150 :                 if (!latest || pcache_meta_seq_after(meta->seq, seq_latest)) {
     101        96928 :                         seq_latest = meta->seq;
     102        96928 :                         latest = (void *)header + (i * meta_max_size);
     103              :                 }
     104              :         }
     105              : 
     106        64660 :         if (!latest)
     107              :                 return NULL;
     108              : 
     109        64392 :         if (copy_mc_to_kernel(meta_ret, latest, meta_size)) {
     110            0 :                 pcache_err("hardware memory error");
     111            0 :                 return ERR_PTR(-EIO);
     112              :         }
     113              : 
     114              :         return latest;
     115              : }
     116              : 
     117              : #endif /* _PCACHE_INTERNAL_H */
        

Generated by: LCOV version 2.0-1