LCOV - code coverage report
Current view: top level - dm-pcache - backing_dev.c (source / functions) Coverage Total Hit
Test: dm_pcache.info Lines: 91.3 % 208 190
Test Date: 2025-08-04 03:13:17 Functions: 100.0 % 19 19
Legend: Lines: hit not hit

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-or-later
       2              : #include <linux/blkdev.h>
       3              : 
       4              : #include "../dm-core.h"
       5              : #include "pcache_internal.h"
       6              : #include "cache_dev.h"
       7              : #include "backing_dev.h"
       8              : #include "cache.h"
       9              : #include "dm_pcache.h"
      10              : 
      11              : static struct kmem_cache *backing_req_cache;
      12              : static struct kmem_cache *backing_bvec_cache;
      13              : 
      14          303 : static void backing_dev_exit(struct pcache_backing_dev *backing_dev)
      15              : {
      16          303 :         mempool_exit(&backing_dev->req_pool);
      17          303 :         mempool_exit(&backing_dev->bvec_pool);
      18              : }
      19              : 
      20              : static void req_submit_fn(struct work_struct *work);
      21              : static void req_complete_fn(struct work_struct *work);
      22          301 : static int backing_dev_init(struct dm_pcache *pcache)
      23              : {
      24          301 :         struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
      25          301 :         int ret;
      26              : 
      27          301 :         ret = mempool_init_slab_pool(&backing_dev->req_pool, 128, backing_req_cache);
      28          301 :         if (ret)
      29            0 :                 goto err;
      30              : 
      31          301 :         ret = mempool_init_slab_pool(&backing_dev->bvec_pool, 128, backing_bvec_cache);
      32          301 :         if (ret)
      33            0 :                 goto req_pool_exit;
      34              : 
      35          301 :         INIT_LIST_HEAD(&backing_dev->submit_list);
      36          301 :         INIT_LIST_HEAD(&backing_dev->complete_list);
      37          301 :         spin_lock_init(&backing_dev->submit_lock);
      38          301 :         spin_lock_init(&backing_dev->complete_lock);
      39          301 :         INIT_WORK(&backing_dev->req_submit_work, req_submit_fn);
      40          301 :         INIT_WORK(&backing_dev->req_complete_work, req_complete_fn);
      41              : 
      42          301 :         return 0;
      43              : 
      44            0 : req_pool_exit:
      45            0 :         mempool_exit(&backing_dev->req_pool);
      46              : err:
      47              :         return ret;
      48              : }
      49              : 
      50          301 : int backing_dev_start(struct dm_pcache *pcache)
      51              : {
      52          301 :         struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
      53          301 :         int ret;
      54              : 
      55          301 :         ret = backing_dev_init(pcache);
      56          301 :         if (ret)
      57              :                 return ret;
      58              : 
      59          301 :         backing_dev->dev_size = bdev_nr_sectors(backing_dev->dm_dev->bdev);
      60              : 
      61          301 :         return 0;
      62              : }
      63              : 
      64          303 : void backing_dev_stop(struct dm_pcache *pcache)
      65              : {
      66          303 :         struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
      67              : 
      68          303 :         flush_work(&backing_dev->req_submit_work);
      69          303 :         flush_work(&backing_dev->req_complete_work);
      70              : 
      71              :         /* There should be no inflight backing_dev_request */
      72          303 :         BUG_ON(!list_empty(&backing_dev->submit_list));
      73          303 :         BUG_ON(!list_empty(&backing_dev->complete_list));
      74              : 
      75          303 :         backing_dev_exit(backing_dev);
      76          303 : }
      77              : 
      78              : /* pcache_backing_dev_req functions */
      79     33370687 : void backing_dev_req_end(struct pcache_backing_dev_req *backing_req)
      80              : {
      81     33370687 :         struct pcache_backing_dev *backing_dev = backing_req->backing_dev;
      82              : 
      83     33370687 :         if (backing_req->end_req)
      84     33370679 :                 backing_req->end_req(backing_req, backing_req->ret);
      85              : 
      86     33370692 :         switch (backing_req->type) {
      87       907638 :         case BACKING_DEV_REQ_TYPE_REQ:
      88       907638 :                 if (backing_req->req.upper_req)
      89       907630 :                         pcache_req_put(backing_req->req.upper_req, backing_req->ret);
      90              :                 break;
      91     32463054 :         case BACKING_DEV_REQ_TYPE_KMEM:
      92     32463054 :                 if (backing_req->kmem.bvecs != backing_req->kmem.inline_bvecs)
      93      4993995 :                         mempool_free(backing_req->kmem.bvecs, &backing_dev->bvec_pool);
      94              :                 break;
      95            0 :         default:
      96            0 :                 BUG();
      97              :         }
      98              : 
      99     33370692 :         mempool_free(backing_req, &backing_dev->req_pool);
     100     33370692 : }
     101              : 
     102      7631683 : static void req_complete_fn(struct work_struct *work)
     103              : {
     104      7631683 :         struct pcache_backing_dev *backing_dev = container_of(work, struct pcache_backing_dev, req_complete_work);
     105      7631683 :         struct pcache_backing_dev_req *backing_req;
     106      7631683 :         LIST_HEAD(tmp_list);
     107              : 
     108      7631683 :         spin_lock_irq(&backing_dev->complete_lock);
     109      7631684 :         list_splice_init(&backing_dev->complete_list, &tmp_list);
     110      7631684 :         spin_unlock_irq(&backing_dev->complete_lock);
     111              : 
     112     48634049 :         while (!list_empty(&tmp_list)) {
     113     33370679 :                 backing_req = list_first_entry(&tmp_list,
     114              :                                             struct pcache_backing_dev_req, node);
     115     33370679 :                 list_del_init(&backing_req->node);
     116     33370679 :                 backing_dev_req_end(backing_req);
     117              :         }
     118      7631686 : }
     119              : 
     120     33370439 : static void backing_dev_bio_end(struct bio *bio)
     121              : {
     122     33370439 :         struct pcache_backing_dev_req *backing_req = bio->bi_private;
     123     33370439 :         struct pcache_backing_dev *backing_dev = backing_req->backing_dev;
     124     33370439 :         unsigned long flags;
     125              : 
     126     33370439 :         backing_req->ret = bio->bi_status;
     127              : 
     128     33370439 :         spin_lock_irqsave(&backing_dev->complete_lock, flags);
     129     33370687 :         list_move_tail(&backing_req->node, &backing_dev->complete_list);
     130     33370687 :         queue_work(BACKING_DEV_TO_PCACHE(backing_dev)->task_wq, &backing_dev->req_complete_work);
     131     33370680 :         spin_unlock_irqrestore(&backing_dev->complete_lock, flags);
     132     33370675 : }
     133              : 
     134       847350 : static void req_submit_fn(struct work_struct *work)
     135              : {
     136       847350 :         struct pcache_backing_dev *backing_dev = container_of(work, struct pcache_backing_dev, req_submit_work);
     137       847350 :         struct pcache_backing_dev_req *backing_req;
     138       847350 :         LIST_HEAD(tmp_list);
     139              : 
     140       847350 :         spin_lock(&backing_dev->submit_lock);
     141       847350 :         list_splice_init(&backing_dev->submit_list, &tmp_list);
     142       847350 :         spin_unlock(&backing_dev->submit_lock);
     143              : 
     144      2602330 :         while (!list_empty(&tmp_list)) {
     145       907630 :                 backing_req = list_first_entry(&tmp_list,
     146              :                                             struct pcache_backing_dev_req, node);
     147       907630 :                 list_del_init(&backing_req->node);
     148       907630 :                 submit_bio_noacct(&backing_req->bio);
     149              :         }
     150       847350 : }
     151              : 
     152     33370450 : void backing_dev_req_submit(struct pcache_backing_dev_req *backing_req, bool direct)
     153              : {
     154     33370450 :         struct pcache_backing_dev *backing_dev = backing_req->backing_dev;
     155              : 
     156     33370450 :         if (direct) {
     157     32463049 :                 submit_bio_noacct(&backing_req->bio);
     158     32463049 :                 return;
     159              :         }
     160              : 
     161       907401 :         spin_lock(&backing_dev->submit_lock);
     162       907630 :         list_add_tail(&backing_req->node, &backing_dev->submit_list);
     163       907630 :         queue_work(BACKING_DEV_TO_PCACHE(backing_dev)->task_wq, &backing_dev->req_submit_work);
     164       907630 :         spin_unlock(&backing_dev->submit_lock);
     165              : }
     166              : 
     167     32463043 : static void bio_map(struct bio *bio, void *base, size_t size)
     168              : {
     169     32463043 :         struct page *page;
     170     32463043 :         unsigned int offset;
     171     32463043 :         unsigned int len;
     172              : 
     173     32463043 :         if (!is_vmalloc_addr(base)) {
     174     16735813 :                 page = virt_to_page(base);
     175     16735813 :                 offset = offset_in_page(base);
     176              : 
     177     16735813 :                 BUG_ON(!bio_add_page(bio, page, size, offset));
     178              :                 return;
     179              :         }
     180              : 
     181              :         flush_kernel_vmap_range(base, size);
     182    167561476 :         while (size) {
     183    151834247 :                 page = vmalloc_to_page(base);
     184    151834518 :                 offset = offset_in_page(base);
     185    151834518 :                 len = min_t(size_t, PAGE_SIZE - offset, size);
     186              : 
     187    151834518 :                 BUG_ON(!bio_add_page(bio, page, len, offset));
     188    151834245 :                 size -= len;
     189    151834245 :                 base += len;
     190              :         }
     191              : }
     192              : 
     193       907869 : static struct pcache_backing_dev_req *req_type_req_alloc(struct pcache_backing_dev *backing_dev,
     194              :                                                         struct pcache_backing_dev_req_opts *opts)
     195              : {
     196       907869 :         struct pcache_request *pcache_req = opts->req.upper_req;
     197       907869 :         struct pcache_backing_dev_req *backing_req;
     198       907869 :         struct bio *orig = pcache_req->bio;
     199              : 
     200       907869 :         backing_req = mempool_alloc(&backing_dev->req_pool, opts->gfp_mask);
     201       907894 :         if (!backing_req)
     202              :                 return NULL;
     203              : 
     204       907502 :         memset(backing_req, 0, sizeof(struct pcache_backing_dev_req));
     205              : 
     206       907502 :         bio_init_clone(backing_dev->dm_dev->bdev, &backing_req->bio, orig, opts->gfp_mask);
     207              : 
     208       907565 :         backing_req->type = BACKING_DEV_REQ_TYPE_REQ;
     209       907565 :         backing_req->backing_dev = backing_dev;
     210              : 
     211       907565 :         return backing_req;
     212              : }
     213              : 
     214     32463041 : static struct pcache_backing_dev_req *kmem_type_req_alloc(struct pcache_backing_dev *backing_dev,
     215              :                                                 struct pcache_backing_dev_req_opts *opts)
     216              : {
     217     32463041 :         struct pcache_backing_dev_req *backing_req;
     218     32463041 :         u32 n_vecs = bio_add_max_vecs(opts->kmem.data, opts->kmem.len);
     219              : 
     220     32463040 :         backing_req = mempool_alloc(&backing_dev->req_pool, opts->gfp_mask);
     221     32463046 :         if (!backing_req)
     222              :                 return NULL;
     223              : 
     224     32463046 :         memset(backing_req, 0, sizeof(struct pcache_backing_dev_req));
     225              : 
     226     32463046 :         if (n_vecs > BACKING_DEV_REQ_INLINE_BVECS) {
     227      4993994 :                 backing_req->kmem.bvecs = mempool_alloc(&backing_dev->bvec_pool, opts->gfp_mask);
     228      4993991 :                 if (!backing_req->kmem.bvecs)
     229            0 :                         goto free_backing_req;
     230              :         } else {
     231     27469052 :                 backing_req->kmem.bvecs = backing_req->kmem.inline_bvecs;
     232              :         }
     233              : 
     234     32463043 :         backing_req->kmem.n_vecs = n_vecs;
     235     32463043 :         backing_req->type = BACKING_DEV_REQ_TYPE_KMEM;
     236     32463043 :         backing_req->backing_dev = backing_dev;
     237              : 
     238     32463043 :         return backing_req;
     239              : 
     240            0 : free_backing_req:
     241            0 :         mempool_free(backing_req, &backing_dev->req_pool);
     242            0 :         return NULL;
     243              : }
     244              : 
     245     33370915 : struct pcache_backing_dev_req *backing_dev_req_alloc(struct pcache_backing_dev *backing_dev,
     246              :                                                 struct pcache_backing_dev_req_opts *opts)
     247              : {
     248     33370915 :         if (opts->type == BACKING_DEV_REQ_TYPE_REQ)
     249       907874 :                 return req_type_req_alloc(backing_dev, opts);
     250              : 
     251     32463041 :         if (opts->type == BACKING_DEV_REQ_TYPE_KMEM)
     252     32463041 :                 return kmem_type_req_alloc(backing_dev, opts);
     253              : 
     254            0 :         BUG();
     255              : }
     256              : 
     257       907491 : static void req_type_req_init(struct pcache_backing_dev_req *backing_req,
     258              :                         struct pcache_backing_dev_req_opts *opts)
     259              : {
     260       907491 :         struct pcache_request *pcache_req = opts->req.upper_req;
     261       907491 :         struct bio *clone;
     262       907491 :         u32 off = opts->req.req_off;
     263       907491 :         u32 len = opts->req.len;
     264              : 
     265       907491 :         clone = &backing_req->bio;
     266       907491 :         BUG_ON(off & SECTOR_MASK);
     267       907491 :         BUG_ON(len & SECTOR_MASK);
     268       907491 :         bio_trim(clone, off >> SECTOR_SHIFT, len >> SECTOR_SHIFT);
     269              : 
     270       907487 :         clone->bi_iter.bi_sector = (pcache_req->off + off) >> SECTOR_SHIFT;
     271       907487 :         clone->bi_private = backing_req;
     272       907487 :         clone->bi_end_io = backing_dev_bio_end;
     273              : 
     274       907487 :         INIT_LIST_HEAD(&backing_req->node);
     275       907487 :         backing_req->end_req     = opts->end_fn;
     276              : 
     277       907487 :         pcache_req_get(pcache_req);
     278       907576 :         backing_req->req.upper_req   = pcache_req;
     279       907576 :         backing_req->req.bio_off     = off;
     280       907576 : }
     281              : 
     282     32463041 : static void kmem_type_req_init(struct pcache_backing_dev_req *backing_req,
     283              :                         struct pcache_backing_dev_req_opts *opts)
     284              : {
     285     32463041 :         struct pcache_backing_dev *backing_dev = backing_req->backing_dev;
     286     32463041 :         struct bio *backing_bio;
     287              : 
     288     32463041 :         bio_init(&backing_req->bio, backing_dev->dm_dev->bdev, backing_req->kmem.bvecs,
     289     32463041 :                         backing_req->kmem.n_vecs, opts->kmem.opf);
     290              : 
     291     32463047 :         backing_bio = &backing_req->bio;
     292     32463047 :         bio_map(backing_bio, opts->kmem.data, opts->kmem.len);
     293              : 
     294     32463043 :         backing_bio->bi_iter.bi_sector = (opts->kmem.backing_off) >> SECTOR_SHIFT;
     295     32463043 :         backing_bio->bi_private = backing_req;
     296     32463043 :         backing_bio->bi_end_io = backing_dev_bio_end;
     297              : 
     298     32463043 :         INIT_LIST_HEAD(&backing_req->node);
     299     32463043 :         backing_req->end_req = opts->end_fn;
     300     32463043 :         backing_req->priv_data       = opts->priv_data;
     301     32463043 : }
     302              : 
     303     33370534 : void backing_dev_req_init(struct pcache_backing_dev_req *backing_req,
     304              :                         struct pcache_backing_dev_req_opts *opts)
     305              : {
     306     33370534 :         if (opts->type == BACKING_DEV_REQ_TYPE_REQ)
     307       907493 :                 return req_type_req_init(backing_req, opts);
     308              : 
     309     32463041 :         if (opts->type == BACKING_DEV_REQ_TYPE_KMEM)
     310     32463041 :                 return kmem_type_req_init(backing_req, opts);
     311              : 
     312            0 :         BUG();
     313              : }
     314              : 
     315     32463037 : struct pcache_backing_dev_req *backing_dev_req_create(struct pcache_backing_dev *backing_dev,
     316              :                                                 struct pcache_backing_dev_req_opts *opts)
     317              : {
     318     32463037 :         struct pcache_backing_dev_req *backing_req;
     319              : 
     320     32463037 :         backing_req = backing_dev_req_alloc(backing_dev, opts);
     321     32463042 :         if (!backing_req)
     322              :                 return NULL;
     323              : 
     324     32463042 :         backing_dev_req_init(backing_req, opts);
     325              : 
     326     32463042 :         return backing_req;
     327              : }
     328              : 
     329      5413564 : void backing_dev_flush(struct pcache_backing_dev *backing_dev)
     330              : {
     331      5413564 :         blkdev_issue_flush(backing_dev->dm_dev->bdev);
     332      5413563 : }
     333              : 
     334          282 : int pcache_backing_init(void)
     335              : {
     336          282 :         u32 max_bvecs = (PCACHE_CACHE_SUBTREE_SIZE >> PAGE_SHIFT) + 1;
     337          282 :         int ret;
     338              : 
     339          282 :         backing_req_cache = KMEM_CACHE(pcache_backing_dev_req, 0);
     340          282 :         if (!backing_req_cache) {
     341            0 :                 ret = -ENOMEM;
     342            0 :                 goto err;
     343              :         }
     344              : 
     345          282 :         backing_bvec_cache = kmem_cache_create("pcache-bvec-slab",
     346              :                                         max_bvecs * sizeof(struct bio_vec),
     347              :                                         0, 0, NULL);
     348          282 :         if (!backing_bvec_cache) {
     349            0 :                 ret = -ENOMEM;
     350            0 :                 goto destroy_req_cache;
     351              :         }
     352              : 
     353              :         return 0;
     354            0 : destroy_req_cache:
     355            0 :         kmem_cache_destroy(backing_req_cache);
     356              : err:
     357              :         return ret;
     358              : }
     359              : 
     360          165 : void pcache_backing_exit(void)
     361              : {
     362          165 :         kmem_cache_destroy(backing_bvec_cache);
     363          165 :         kmem_cache_destroy(backing_req_cache);
     364          165 : }
        

Generated by: LCOV version 2.0-1