Hello Dongsheng Yang,

Commit 1d57628ff95b ("dm-pcache: add persistent cache target in
device-mapper") from Aug 12, 2025 (linux-next), leads to the
following Smatch static checker warning:

        drivers/md/dm-pcache/cache_segment.c:263 cache_seg_gen_increase()
        warn: sleeping in atomic context

drivers/md/dm-pcache/cache_segment.c
    257 static void cache_seg_gen_increase(struct pcache_cache_segment 
*cache_seg)
    258 {
    259         spin_lock(&cache_seg->gen_lock);
    260         cache_seg->gen++;
    261         spin_unlock(&cache_seg->gen_lock);
    262 
--> 263         cache_seg_ctrl_write(cache_seg);

cache_seg_ctrl_write() takes a mutex so it can't be called with
preemption disabled.

    264 }

There are a few callers which Smatch says have preemption disabled:
The call tree is kind of messy but the point is that there are four
callers which Smatch says disable preemption.

miss_read_end_req() <- disables preempt
-> cache_data_alloc() <- disables preempt
miss_read_end_req() <- disables preempt <duplicate>
cache_write() <- disables preempt
   -> cache_seg_put()
      -> cache_seg_invalidate()
         -> cache_seg_gen_increase()

drivers/md/dm-pcache/cache_req.c
    36  static int cache_data_alloc(struct pcache_cache *cache, struct 
pcache_cache_key *key)
    37  {
    38          struct pcache_cache_data_head *data_head;
    39          struct pcache_cache_pos *head_pos;
    40          struct pcache_cache_segment *cache_seg;
    41          u32 seg_remain;
    42          u32 allocated = 0, to_alloc;
    43          int ret = 0;
    44  
    45          preempt_disable();
                ^^^^^^^^^^^^^^^^^^

    46          data_head = get_data_head(cache);
    47  again:
    48          to_alloc = key->len - allocated;
    49          if (!data_head->head_pos.cache_seg) {
    50                  seg_remain = 0;
    51          } else {
    52                  cache_pos_copy(&key->cache_pos, &data_head->head_pos);
    53                  key->seg_gen = key->cache_pos.cache_seg->gen;
    54  
    55                  head_pos = &data_head->head_pos;
    56                  cache_seg = head_pos->cache_seg;
    57                  seg_remain = cache_seg_remain(head_pos);
    58          }
    59  
    60          if (seg_remain > to_alloc) {
    61                  /* If remaining space in segment is sufficient for the 
cache key, allocate it. */
    62                  cache_pos_advance(head_pos, to_alloc);
    63                  allocated += to_alloc;
    64                  cache_seg_get(cache_seg);
    65          } else if (seg_remain) {
    66                  /* If remaining space is not enough, allocate the 
remaining space and adjust the cache key length. */
    67                  cache_pos_advance(head_pos, seg_remain);
    68                  key->len = seg_remain;
    69  
    70                  /* Get for key: obtain a reference to the cache segment 
for the key. */
    71                  cache_seg_get(cache_seg);
    72                  /* Put for head_pos->cache_seg: release the reference 
for the current head's segment. */
    73                  cache_seg_put(head_pos->cache_seg);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If we still are holding a second reference, then this warning is a false
positive, but the commen suggests that we might actually free it.

    74                  head_pos->cache_seg = NULL;
    75          } else {
    76                  /* Initialize a new data head if no segment is 
available. */
    77                  ret = cache_data_head_init(cache);
    78                  if (ret)
    79                          goto out;
    80  
    81                  goto again;
    82          }
    83  
    84  out:
    85          preempt_enable();
    86  
    87          return ret;
    88  }

regards,
dan carpenter

Reply via email to