1*1d57628fSDongsheng Yang // SPDX-License-Identifier: GPL-2.0-or-later 2*1d57628fSDongsheng Yang #include <linux/module.h> 3*1d57628fSDongsheng Yang #include <linux/blkdev.h> 4*1d57628fSDongsheng Yang #include <linux/bio.h> 5*1d57628fSDongsheng Yang 6*1d57628fSDongsheng Yang #include "../dm-core.h" 7*1d57628fSDongsheng Yang #include "cache_dev.h" 8*1d57628fSDongsheng Yang #include "backing_dev.h" 9*1d57628fSDongsheng Yang #include "cache.h" 10*1d57628fSDongsheng Yang #include "dm_pcache.h" 11*1d57628fSDongsheng Yang 12*1d57628fSDongsheng Yang void pcache_defer_reqs_kick(struct dm_pcache *pcache) 13*1d57628fSDongsheng Yang { 14*1d57628fSDongsheng Yang struct pcache_cache *cache = &pcache->cache; 15*1d57628fSDongsheng Yang 16*1d57628fSDongsheng Yang spin_lock(&cache->seg_map_lock); 17*1d57628fSDongsheng Yang if (!cache->cache_full) 18*1d57628fSDongsheng Yang queue_work(pcache->task_wq, &pcache->defered_req_work); 19*1d57628fSDongsheng Yang spin_unlock(&cache->seg_map_lock); 20*1d57628fSDongsheng Yang } 21*1d57628fSDongsheng Yang 22*1d57628fSDongsheng Yang static void defer_req(struct pcache_request *pcache_req) 23*1d57628fSDongsheng Yang { 24*1d57628fSDongsheng Yang struct dm_pcache *pcache = pcache_req->pcache; 25*1d57628fSDongsheng Yang 26*1d57628fSDongsheng Yang BUG_ON(!list_empty(&pcache_req->list_node)); 27*1d57628fSDongsheng Yang 28*1d57628fSDongsheng Yang spin_lock(&pcache->defered_req_list_lock); 29*1d57628fSDongsheng Yang list_add(&pcache_req->list_node, &pcache->defered_req_list); 30*1d57628fSDongsheng Yang pcache_defer_reqs_kick(pcache); 31*1d57628fSDongsheng Yang spin_unlock(&pcache->defered_req_list_lock); 32*1d57628fSDongsheng Yang } 33*1d57628fSDongsheng Yang 34*1d57628fSDongsheng Yang static void defered_req_fn(struct work_struct *work) 35*1d57628fSDongsheng Yang { 36*1d57628fSDongsheng Yang struct dm_pcache *pcache = container_of(work, struct dm_pcache, defered_req_work); 37*1d57628fSDongsheng Yang struct pcache_request *pcache_req; 38*1d57628fSDongsheng Yang LIST_HEAD(tmp_list); 39*1d57628fSDongsheng Yang int ret; 40*1d57628fSDongsheng Yang 41*1d57628fSDongsheng Yang if (pcache_is_stopping(pcache)) 42*1d57628fSDongsheng Yang return; 43*1d57628fSDongsheng Yang 44*1d57628fSDongsheng Yang spin_lock(&pcache->defered_req_list_lock); 45*1d57628fSDongsheng Yang list_splice_init(&pcache->defered_req_list, &tmp_list); 46*1d57628fSDongsheng Yang spin_unlock(&pcache->defered_req_list_lock); 47*1d57628fSDongsheng Yang 48*1d57628fSDongsheng Yang while (!list_empty(&tmp_list)) { 49*1d57628fSDongsheng Yang pcache_req = list_first_entry(&tmp_list, 50*1d57628fSDongsheng Yang struct pcache_request, list_node); 51*1d57628fSDongsheng Yang list_del_init(&pcache_req->list_node); 52*1d57628fSDongsheng Yang pcache_req->ret = 0; 53*1d57628fSDongsheng Yang ret = pcache_cache_handle_req(&pcache->cache, pcache_req); 54*1d57628fSDongsheng Yang if (ret == -EBUSY) 55*1d57628fSDongsheng Yang defer_req(pcache_req); 56*1d57628fSDongsheng Yang else 57*1d57628fSDongsheng Yang pcache_req_put(pcache_req, ret); 58*1d57628fSDongsheng Yang } 59*1d57628fSDongsheng Yang } 60*1d57628fSDongsheng Yang 61*1d57628fSDongsheng Yang void pcache_req_get(struct pcache_request *pcache_req) 62*1d57628fSDongsheng Yang { 63*1d57628fSDongsheng Yang kref_get(&pcache_req->ref); 64*1d57628fSDongsheng Yang } 65*1d57628fSDongsheng Yang 66*1d57628fSDongsheng Yang static void end_req(struct kref *ref) 67*1d57628fSDongsheng Yang { 68*1d57628fSDongsheng Yang struct pcache_request *pcache_req = container_of(ref, struct pcache_request, ref); 69*1d57628fSDongsheng Yang struct dm_pcache *pcache = pcache_req->pcache; 70*1d57628fSDongsheng Yang struct bio *bio = pcache_req->bio; 71*1d57628fSDongsheng Yang int ret = pcache_req->ret; 72*1d57628fSDongsheng Yang 73*1d57628fSDongsheng Yang if (ret == -EBUSY) { 74*1d57628fSDongsheng Yang pcache_req_get(pcache_req); 75*1d57628fSDongsheng Yang defer_req(pcache_req); 76*1d57628fSDongsheng Yang } else { 77*1d57628fSDongsheng Yang bio->bi_status = errno_to_blk_status(ret); 78*1d57628fSDongsheng Yang bio_endio(bio); 79*1d57628fSDongsheng Yang 80*1d57628fSDongsheng Yang if (atomic_dec_and_test(&pcache->inflight_reqs)) 81*1d57628fSDongsheng Yang wake_up(&pcache->inflight_wq); 82*1d57628fSDongsheng Yang } 83*1d57628fSDongsheng Yang } 84*1d57628fSDongsheng Yang 85*1d57628fSDongsheng Yang void pcache_req_put(struct pcache_request *pcache_req, int ret) 86*1d57628fSDongsheng Yang { 87*1d57628fSDongsheng Yang /* Set the return status if it is not already set */ 88*1d57628fSDongsheng Yang if (ret && !pcache_req->ret) 89*1d57628fSDongsheng Yang pcache_req->ret = ret; 90*1d57628fSDongsheng Yang 91*1d57628fSDongsheng Yang kref_put(&pcache_req->ref, end_req); 92*1d57628fSDongsheng Yang } 93*1d57628fSDongsheng Yang 94*1d57628fSDongsheng Yang static bool at_least_one_arg(struct dm_arg_set *as, char **error) 95*1d57628fSDongsheng Yang { 96*1d57628fSDongsheng Yang if (!as->argc) { 97*1d57628fSDongsheng Yang *error = "Insufficient args"; 98*1d57628fSDongsheng Yang return false; 99*1d57628fSDongsheng Yang } 100*1d57628fSDongsheng Yang 101*1d57628fSDongsheng Yang return true; 102*1d57628fSDongsheng Yang } 103*1d57628fSDongsheng Yang 104*1d57628fSDongsheng Yang static int parse_cache_dev(struct dm_pcache *pcache, struct dm_arg_set *as, 105*1d57628fSDongsheng Yang char **error) 106*1d57628fSDongsheng Yang { 107*1d57628fSDongsheng Yang int ret; 108*1d57628fSDongsheng Yang 109*1d57628fSDongsheng Yang if (!at_least_one_arg(as, error)) 110*1d57628fSDongsheng Yang return -EINVAL; 111*1d57628fSDongsheng Yang ret = dm_get_device(pcache->ti, dm_shift_arg(as), 112*1d57628fSDongsheng Yang BLK_OPEN_READ | BLK_OPEN_WRITE, 113*1d57628fSDongsheng Yang &pcache->cache_dev.dm_dev); 114*1d57628fSDongsheng Yang if (ret) { 115*1d57628fSDongsheng Yang *error = "Error opening cache device"; 116*1d57628fSDongsheng Yang return ret; 117*1d57628fSDongsheng Yang } 118*1d57628fSDongsheng Yang 119*1d57628fSDongsheng Yang return 0; 120*1d57628fSDongsheng Yang } 121*1d57628fSDongsheng Yang 122*1d57628fSDongsheng Yang static int parse_backing_dev(struct dm_pcache *pcache, struct dm_arg_set *as, 123*1d57628fSDongsheng Yang char **error) 124*1d57628fSDongsheng Yang { 125*1d57628fSDongsheng Yang int ret; 126*1d57628fSDongsheng Yang 127*1d57628fSDongsheng Yang if (!at_least_one_arg(as, error)) 128*1d57628fSDongsheng Yang return -EINVAL; 129*1d57628fSDongsheng Yang 130*1d57628fSDongsheng Yang ret = dm_get_device(pcache->ti, dm_shift_arg(as), 131*1d57628fSDongsheng Yang BLK_OPEN_READ | BLK_OPEN_WRITE, 132*1d57628fSDongsheng Yang &pcache->backing_dev.dm_dev); 133*1d57628fSDongsheng Yang if (ret) { 134*1d57628fSDongsheng Yang *error = "Error opening backing device"; 135*1d57628fSDongsheng Yang return ret; 136*1d57628fSDongsheng Yang } 137*1d57628fSDongsheng Yang 138*1d57628fSDongsheng Yang return 0; 139*1d57628fSDongsheng Yang } 140*1d57628fSDongsheng Yang 141*1d57628fSDongsheng Yang static void pcache_init_opts(struct pcache_cache_options *opts) 142*1d57628fSDongsheng Yang { 143*1d57628fSDongsheng Yang opts->cache_mode = PCACHE_CACHE_MODE_WRITEBACK; 144*1d57628fSDongsheng Yang opts->data_crc = false; 145*1d57628fSDongsheng Yang } 146*1d57628fSDongsheng Yang 147*1d57628fSDongsheng Yang static int parse_cache_opts(struct dm_pcache *pcache, struct dm_arg_set *as, 148*1d57628fSDongsheng Yang char **error) 149*1d57628fSDongsheng Yang { 150*1d57628fSDongsheng Yang struct pcache_cache_options *opts = &pcache->opts; 151*1d57628fSDongsheng Yang static const struct dm_arg _args[] = { 152*1d57628fSDongsheng Yang {0, 4, "Invalid number of cache option arguments"}, 153*1d57628fSDongsheng Yang }; 154*1d57628fSDongsheng Yang unsigned int argc; 155*1d57628fSDongsheng Yang const char *arg; 156*1d57628fSDongsheng Yang int ret; 157*1d57628fSDongsheng Yang 158*1d57628fSDongsheng Yang pcache_init_opts(opts); 159*1d57628fSDongsheng Yang if (!as->argc) 160*1d57628fSDongsheng Yang return 0; 161*1d57628fSDongsheng Yang 162*1d57628fSDongsheng Yang ret = dm_read_arg_group(_args, as, &argc, error); 163*1d57628fSDongsheng Yang if (ret) 164*1d57628fSDongsheng Yang return -EINVAL; 165*1d57628fSDongsheng Yang 166*1d57628fSDongsheng Yang while (argc) { 167*1d57628fSDongsheng Yang arg = dm_shift_arg(as); 168*1d57628fSDongsheng Yang argc--; 169*1d57628fSDongsheng Yang 170*1d57628fSDongsheng Yang if (!strcmp(arg, "cache_mode")) { 171*1d57628fSDongsheng Yang arg = dm_shift_arg(as); 172*1d57628fSDongsheng Yang if (!strcmp(arg, "writeback")) { 173*1d57628fSDongsheng Yang opts->cache_mode = PCACHE_CACHE_MODE_WRITEBACK; 174*1d57628fSDongsheng Yang } else { 175*1d57628fSDongsheng Yang *error = "Invalid cache mode parameter"; 176*1d57628fSDongsheng Yang return -EINVAL; 177*1d57628fSDongsheng Yang } 178*1d57628fSDongsheng Yang argc--; 179*1d57628fSDongsheng Yang } else if (!strcmp(arg, "data_crc")) { 180*1d57628fSDongsheng Yang arg = dm_shift_arg(as); 181*1d57628fSDongsheng Yang if (!strcmp(arg, "true")) { 182*1d57628fSDongsheng Yang opts->data_crc = true; 183*1d57628fSDongsheng Yang } else if (!strcmp(arg, "false")) { 184*1d57628fSDongsheng Yang opts->data_crc = false; 185*1d57628fSDongsheng Yang } else { 186*1d57628fSDongsheng Yang *error = "Invalid data crc parameter"; 187*1d57628fSDongsheng Yang return -EINVAL; 188*1d57628fSDongsheng Yang } 189*1d57628fSDongsheng Yang argc--; 190*1d57628fSDongsheng Yang } else { 191*1d57628fSDongsheng Yang *error = "Unrecognised cache option requested"; 192*1d57628fSDongsheng Yang return -EINVAL; 193*1d57628fSDongsheng Yang } 194*1d57628fSDongsheng Yang } 195*1d57628fSDongsheng Yang 196*1d57628fSDongsheng Yang return 0; 197*1d57628fSDongsheng Yang } 198*1d57628fSDongsheng Yang 199*1d57628fSDongsheng Yang static int pcache_start(struct dm_pcache *pcache, char **error) 200*1d57628fSDongsheng Yang { 201*1d57628fSDongsheng Yang int ret; 202*1d57628fSDongsheng Yang 203*1d57628fSDongsheng Yang ret = cache_dev_start(pcache); 204*1d57628fSDongsheng Yang if (ret) { 205*1d57628fSDongsheng Yang *error = "Failed to start cache dev"; 206*1d57628fSDongsheng Yang return ret; 207*1d57628fSDongsheng Yang } 208*1d57628fSDongsheng Yang 209*1d57628fSDongsheng Yang ret = backing_dev_start(pcache); 210*1d57628fSDongsheng Yang if (ret) { 211*1d57628fSDongsheng Yang *error = "Failed to start backing dev"; 212*1d57628fSDongsheng Yang goto stop_cache; 213*1d57628fSDongsheng Yang } 214*1d57628fSDongsheng Yang 215*1d57628fSDongsheng Yang ret = pcache_cache_start(pcache); 216*1d57628fSDongsheng Yang if (ret) { 217*1d57628fSDongsheng Yang *error = "Failed to start pcache"; 218*1d57628fSDongsheng Yang goto stop_backing; 219*1d57628fSDongsheng Yang } 220*1d57628fSDongsheng Yang 221*1d57628fSDongsheng Yang return 0; 222*1d57628fSDongsheng Yang stop_backing: 223*1d57628fSDongsheng Yang backing_dev_stop(pcache); 224*1d57628fSDongsheng Yang stop_cache: 225*1d57628fSDongsheng Yang cache_dev_stop(pcache); 226*1d57628fSDongsheng Yang 227*1d57628fSDongsheng Yang return ret; 228*1d57628fSDongsheng Yang } 229*1d57628fSDongsheng Yang 230*1d57628fSDongsheng Yang static void pcache_destroy_args(struct dm_pcache *pcache) 231*1d57628fSDongsheng Yang { 232*1d57628fSDongsheng Yang if (pcache->cache_dev.dm_dev) 233*1d57628fSDongsheng Yang dm_put_device(pcache->ti, pcache->cache_dev.dm_dev); 234*1d57628fSDongsheng Yang if (pcache->backing_dev.dm_dev) 235*1d57628fSDongsheng Yang dm_put_device(pcache->ti, pcache->backing_dev.dm_dev); 236*1d57628fSDongsheng Yang } 237*1d57628fSDongsheng Yang 238*1d57628fSDongsheng Yang static int pcache_parse_args(struct dm_pcache *pcache, unsigned int argc, char **argv, 239*1d57628fSDongsheng Yang char **error) 240*1d57628fSDongsheng Yang { 241*1d57628fSDongsheng Yang struct dm_arg_set as; 242*1d57628fSDongsheng Yang int ret; 243*1d57628fSDongsheng Yang 244*1d57628fSDongsheng Yang as.argc = argc; 245*1d57628fSDongsheng Yang as.argv = argv; 246*1d57628fSDongsheng Yang 247*1d57628fSDongsheng Yang /* 248*1d57628fSDongsheng Yang * Parse cache device 249*1d57628fSDongsheng Yang */ 250*1d57628fSDongsheng Yang ret = parse_cache_dev(pcache, &as, error); 251*1d57628fSDongsheng Yang if (ret) 252*1d57628fSDongsheng Yang return ret; 253*1d57628fSDongsheng Yang /* 254*1d57628fSDongsheng Yang * Parse backing device 255*1d57628fSDongsheng Yang */ 256*1d57628fSDongsheng Yang ret = parse_backing_dev(pcache, &as, error); 257*1d57628fSDongsheng Yang if (ret) 258*1d57628fSDongsheng Yang goto out; 259*1d57628fSDongsheng Yang /* 260*1d57628fSDongsheng Yang * Parse optional arguments 261*1d57628fSDongsheng Yang */ 262*1d57628fSDongsheng Yang ret = parse_cache_opts(pcache, &as, error); 263*1d57628fSDongsheng Yang if (ret) 264*1d57628fSDongsheng Yang goto out; 265*1d57628fSDongsheng Yang 266*1d57628fSDongsheng Yang return 0; 267*1d57628fSDongsheng Yang out: 268*1d57628fSDongsheng Yang pcache_destroy_args(pcache); 269*1d57628fSDongsheng Yang return ret; 270*1d57628fSDongsheng Yang } 271*1d57628fSDongsheng Yang 272*1d57628fSDongsheng Yang static int dm_pcache_ctr(struct dm_target *ti, unsigned int argc, char **argv) 273*1d57628fSDongsheng Yang { 274*1d57628fSDongsheng Yang struct mapped_device *md = ti->table->md; 275*1d57628fSDongsheng Yang struct dm_pcache *pcache; 276*1d57628fSDongsheng Yang int ret; 277*1d57628fSDongsheng Yang 278*1d57628fSDongsheng Yang if (md->map) { 279*1d57628fSDongsheng Yang ti->error = "Don't support table loading for live md"; 280*1d57628fSDongsheng Yang return -EOPNOTSUPP; 281*1d57628fSDongsheng Yang } 282*1d57628fSDongsheng Yang 283*1d57628fSDongsheng Yang /* Allocate memory for the cache structure */ 284*1d57628fSDongsheng Yang pcache = kzalloc(sizeof(struct dm_pcache), GFP_KERNEL); 285*1d57628fSDongsheng Yang if (!pcache) 286*1d57628fSDongsheng Yang return -ENOMEM; 287*1d57628fSDongsheng Yang 288*1d57628fSDongsheng Yang pcache->task_wq = alloc_workqueue("pcache-%s-wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 289*1d57628fSDongsheng Yang 0, md->name); 290*1d57628fSDongsheng Yang if (!pcache->task_wq) { 291*1d57628fSDongsheng Yang ret = -ENOMEM; 292*1d57628fSDongsheng Yang goto free_pcache; 293*1d57628fSDongsheng Yang } 294*1d57628fSDongsheng Yang 295*1d57628fSDongsheng Yang spin_lock_init(&pcache->defered_req_list_lock); 296*1d57628fSDongsheng Yang INIT_LIST_HEAD(&pcache->defered_req_list); 297*1d57628fSDongsheng Yang INIT_WORK(&pcache->defered_req_work, defered_req_fn); 298*1d57628fSDongsheng Yang pcache->ti = ti; 299*1d57628fSDongsheng Yang 300*1d57628fSDongsheng Yang ret = pcache_parse_args(pcache, argc, argv, &ti->error); 301*1d57628fSDongsheng Yang if (ret) 302*1d57628fSDongsheng Yang goto destroy_wq; 303*1d57628fSDongsheng Yang 304*1d57628fSDongsheng Yang ret = pcache_start(pcache, &ti->error); 305*1d57628fSDongsheng Yang if (ret) 306*1d57628fSDongsheng Yang goto destroy_args; 307*1d57628fSDongsheng Yang 308*1d57628fSDongsheng Yang ti->num_flush_bios = 1; 309*1d57628fSDongsheng Yang ti->flush_supported = true; 310*1d57628fSDongsheng Yang ti->per_io_data_size = sizeof(struct pcache_request); 311*1d57628fSDongsheng Yang ti->private = pcache; 312*1d57628fSDongsheng Yang atomic_set(&pcache->inflight_reqs, 0); 313*1d57628fSDongsheng Yang atomic_set(&pcache->state, PCACHE_STATE_RUNNING); 314*1d57628fSDongsheng Yang init_waitqueue_head(&pcache->inflight_wq); 315*1d57628fSDongsheng Yang 316*1d57628fSDongsheng Yang return 0; 317*1d57628fSDongsheng Yang destroy_args: 318*1d57628fSDongsheng Yang pcache_destroy_args(pcache); 319*1d57628fSDongsheng Yang destroy_wq: 320*1d57628fSDongsheng Yang destroy_workqueue(pcache->task_wq); 321*1d57628fSDongsheng Yang free_pcache: 322*1d57628fSDongsheng Yang kfree(pcache); 323*1d57628fSDongsheng Yang 324*1d57628fSDongsheng Yang return ret; 325*1d57628fSDongsheng Yang } 326*1d57628fSDongsheng Yang 327*1d57628fSDongsheng Yang static void defer_req_stop(struct dm_pcache *pcache) 328*1d57628fSDongsheng Yang { 329*1d57628fSDongsheng Yang struct pcache_request *pcache_req; 330*1d57628fSDongsheng Yang LIST_HEAD(tmp_list); 331*1d57628fSDongsheng Yang 332*1d57628fSDongsheng Yang flush_work(&pcache->defered_req_work); 333*1d57628fSDongsheng Yang 334*1d57628fSDongsheng Yang spin_lock(&pcache->defered_req_list_lock); 335*1d57628fSDongsheng Yang list_splice_init(&pcache->defered_req_list, &tmp_list); 336*1d57628fSDongsheng Yang spin_unlock(&pcache->defered_req_list_lock); 337*1d57628fSDongsheng Yang 338*1d57628fSDongsheng Yang while (!list_empty(&tmp_list)) { 339*1d57628fSDongsheng Yang pcache_req = list_first_entry(&tmp_list, 340*1d57628fSDongsheng Yang struct pcache_request, list_node); 341*1d57628fSDongsheng Yang list_del_init(&pcache_req->list_node); 342*1d57628fSDongsheng Yang pcache_req_put(pcache_req, -EIO); 343*1d57628fSDongsheng Yang } 344*1d57628fSDongsheng Yang } 345*1d57628fSDongsheng Yang 346*1d57628fSDongsheng Yang static void dm_pcache_dtr(struct dm_target *ti) 347*1d57628fSDongsheng Yang { 348*1d57628fSDongsheng Yang struct dm_pcache *pcache; 349*1d57628fSDongsheng Yang 350*1d57628fSDongsheng Yang pcache = ti->private; 351*1d57628fSDongsheng Yang atomic_set(&pcache->state, PCACHE_STATE_STOPPING); 352*1d57628fSDongsheng Yang defer_req_stop(pcache); 353*1d57628fSDongsheng Yang 354*1d57628fSDongsheng Yang wait_event(pcache->inflight_wq, 355*1d57628fSDongsheng Yang atomic_read(&pcache->inflight_reqs) == 0); 356*1d57628fSDongsheng Yang 357*1d57628fSDongsheng Yang pcache_cache_stop(pcache); 358*1d57628fSDongsheng Yang backing_dev_stop(pcache); 359*1d57628fSDongsheng Yang cache_dev_stop(pcache); 360*1d57628fSDongsheng Yang 361*1d57628fSDongsheng Yang pcache_destroy_args(pcache); 362*1d57628fSDongsheng Yang drain_workqueue(pcache->task_wq); 363*1d57628fSDongsheng Yang destroy_workqueue(pcache->task_wq); 364*1d57628fSDongsheng Yang 365*1d57628fSDongsheng Yang kfree(pcache); 366*1d57628fSDongsheng Yang } 367*1d57628fSDongsheng Yang 368*1d57628fSDongsheng Yang static int dm_pcache_map_bio(struct dm_target *ti, struct bio *bio) 369*1d57628fSDongsheng Yang { 370*1d57628fSDongsheng Yang struct pcache_request *pcache_req = dm_per_bio_data(bio, sizeof(struct pcache_request)); 371*1d57628fSDongsheng Yang struct dm_pcache *pcache = ti->private; 372*1d57628fSDongsheng Yang int ret; 373*1d57628fSDongsheng Yang 374*1d57628fSDongsheng Yang pcache_req->pcache = pcache; 375*1d57628fSDongsheng Yang kref_init(&pcache_req->ref); 376*1d57628fSDongsheng Yang pcache_req->ret = 0; 377*1d57628fSDongsheng Yang pcache_req->bio = bio; 378*1d57628fSDongsheng Yang pcache_req->off = (u64)bio->bi_iter.bi_sector << SECTOR_SHIFT; 379*1d57628fSDongsheng Yang pcache_req->data_len = bio->bi_iter.bi_size; 380*1d57628fSDongsheng Yang INIT_LIST_HEAD(&pcache_req->list_node); 381*1d57628fSDongsheng Yang atomic_inc(&pcache->inflight_reqs); 382*1d57628fSDongsheng Yang 383*1d57628fSDongsheng Yang ret = pcache_cache_handle_req(&pcache->cache, pcache_req); 384*1d57628fSDongsheng Yang if (ret == -EBUSY) 385*1d57628fSDongsheng Yang defer_req(pcache_req); 386*1d57628fSDongsheng Yang else 387*1d57628fSDongsheng Yang pcache_req_put(pcache_req, ret); 388*1d57628fSDongsheng Yang 389*1d57628fSDongsheng Yang return DM_MAPIO_SUBMITTED; 390*1d57628fSDongsheng Yang } 391*1d57628fSDongsheng Yang 392*1d57628fSDongsheng Yang static void dm_pcache_status(struct dm_target *ti, status_type_t type, 393*1d57628fSDongsheng Yang unsigned int status_flags, char *result, 394*1d57628fSDongsheng Yang unsigned int maxlen) 395*1d57628fSDongsheng Yang { 396*1d57628fSDongsheng Yang struct dm_pcache *pcache = ti->private; 397*1d57628fSDongsheng Yang struct pcache_cache_dev *cache_dev = &pcache->cache_dev; 398*1d57628fSDongsheng Yang struct pcache_backing_dev *backing_dev = &pcache->backing_dev; 399*1d57628fSDongsheng Yang struct pcache_cache *cache = &pcache->cache; 400*1d57628fSDongsheng Yang unsigned int sz = 0; 401*1d57628fSDongsheng Yang 402*1d57628fSDongsheng Yang switch (type) { 403*1d57628fSDongsheng Yang case STATUSTYPE_INFO: 404*1d57628fSDongsheng Yang DMEMIT("%x %u %u %u %u %x %u:%u %u:%u %u:%u", 405*1d57628fSDongsheng Yang cache_dev->sb_flags, 406*1d57628fSDongsheng Yang cache_dev->seg_num, 407*1d57628fSDongsheng Yang cache->n_segs, 408*1d57628fSDongsheng Yang bitmap_weight(cache->seg_map, cache->n_segs), 409*1d57628fSDongsheng Yang pcache_cache_get_gc_percent(cache), 410*1d57628fSDongsheng Yang cache->cache_info.flags, 411*1d57628fSDongsheng Yang cache->key_head.cache_seg->cache_seg_id, 412*1d57628fSDongsheng Yang cache->key_head.seg_off, 413*1d57628fSDongsheng Yang cache->dirty_tail.cache_seg->cache_seg_id, 414*1d57628fSDongsheng Yang cache->dirty_tail.seg_off, 415*1d57628fSDongsheng Yang cache->key_tail.cache_seg->cache_seg_id, 416*1d57628fSDongsheng Yang cache->key_tail.seg_off); 417*1d57628fSDongsheng Yang break; 418*1d57628fSDongsheng Yang case STATUSTYPE_TABLE: 419*1d57628fSDongsheng Yang DMEMIT("%s %s 4 cache_mode writeback crc %s", 420*1d57628fSDongsheng Yang cache_dev->dm_dev->name, 421*1d57628fSDongsheng Yang backing_dev->dm_dev->name, 422*1d57628fSDongsheng Yang cache_data_crc_on(cache) ? "true" : "false"); 423*1d57628fSDongsheng Yang break; 424*1d57628fSDongsheng Yang case STATUSTYPE_IMA: 425*1d57628fSDongsheng Yang *result = '\0'; 426*1d57628fSDongsheng Yang break; 427*1d57628fSDongsheng Yang } 428*1d57628fSDongsheng Yang } 429*1d57628fSDongsheng Yang 430*1d57628fSDongsheng Yang static int dm_pcache_message(struct dm_target *ti, unsigned int argc, 431*1d57628fSDongsheng Yang char **argv, char *result, unsigned int maxlen) 432*1d57628fSDongsheng Yang { 433*1d57628fSDongsheng Yang struct dm_pcache *pcache = ti->private; 434*1d57628fSDongsheng Yang unsigned long val; 435*1d57628fSDongsheng Yang 436*1d57628fSDongsheng Yang if (argc != 2) 437*1d57628fSDongsheng Yang goto err; 438*1d57628fSDongsheng Yang 439*1d57628fSDongsheng Yang if (!strcasecmp(argv[0], "gc_percent")) { 440*1d57628fSDongsheng Yang if (kstrtoul(argv[1], 10, &val)) 441*1d57628fSDongsheng Yang goto err; 442*1d57628fSDongsheng Yang 443*1d57628fSDongsheng Yang return pcache_cache_set_gc_percent(&pcache->cache, val); 444*1d57628fSDongsheng Yang } 445*1d57628fSDongsheng Yang err: 446*1d57628fSDongsheng Yang return -EINVAL; 447*1d57628fSDongsheng Yang } 448*1d57628fSDongsheng Yang 449*1d57628fSDongsheng Yang static struct target_type dm_pcache_target = { 450*1d57628fSDongsheng Yang .name = "pcache", 451*1d57628fSDongsheng Yang .version = {0, 1, 0}, 452*1d57628fSDongsheng Yang .module = THIS_MODULE, 453*1d57628fSDongsheng Yang .features = DM_TARGET_SINGLETON, 454*1d57628fSDongsheng Yang .ctr = dm_pcache_ctr, 455*1d57628fSDongsheng Yang .dtr = dm_pcache_dtr, 456*1d57628fSDongsheng Yang .map = dm_pcache_map_bio, 457*1d57628fSDongsheng Yang .status = dm_pcache_status, 458*1d57628fSDongsheng Yang .message = dm_pcache_message, 459*1d57628fSDongsheng Yang }; 460*1d57628fSDongsheng Yang 461*1d57628fSDongsheng Yang static int __init dm_pcache_init(void) 462*1d57628fSDongsheng Yang { 463*1d57628fSDongsheng Yang int ret; 464*1d57628fSDongsheng Yang 465*1d57628fSDongsheng Yang ret = pcache_backing_init(); 466*1d57628fSDongsheng Yang if (ret) 467*1d57628fSDongsheng Yang goto err; 468*1d57628fSDongsheng Yang 469*1d57628fSDongsheng Yang ret = pcache_cache_init(); 470*1d57628fSDongsheng Yang if (ret) 471*1d57628fSDongsheng Yang goto backing_exit; 472*1d57628fSDongsheng Yang 473*1d57628fSDongsheng Yang ret = dm_register_target(&dm_pcache_target); 474*1d57628fSDongsheng Yang if (ret) 475*1d57628fSDongsheng Yang goto cache_exit; 476*1d57628fSDongsheng Yang return 0; 477*1d57628fSDongsheng Yang 478*1d57628fSDongsheng Yang cache_exit: 479*1d57628fSDongsheng Yang pcache_cache_exit(); 480*1d57628fSDongsheng Yang backing_exit: 481*1d57628fSDongsheng Yang pcache_backing_exit(); 482*1d57628fSDongsheng Yang err: 483*1d57628fSDongsheng Yang return ret; 484*1d57628fSDongsheng Yang } 485*1d57628fSDongsheng Yang module_init(dm_pcache_init); 486*1d57628fSDongsheng Yang 487*1d57628fSDongsheng Yang static void __exit dm_pcache_exit(void) 488*1d57628fSDongsheng Yang { 489*1d57628fSDongsheng Yang dm_unregister_target(&dm_pcache_target); 490*1d57628fSDongsheng Yang pcache_cache_exit(); 491*1d57628fSDongsheng Yang pcache_backing_exit(); 492*1d57628fSDongsheng Yang } 493*1d57628fSDongsheng Yang module_exit(dm_pcache_exit); 494*1d57628fSDongsheng Yang 495*1d57628fSDongsheng Yang MODULE_DESCRIPTION("dm-pcache Persistent Cache for block device"); 496*1d57628fSDongsheng Yang MODULE_AUTHOR("Dongsheng Yang <dongsheng.yang@linux.dev>"); 497*1d57628fSDongsheng Yang MODULE_LICENSE("GPL"); 498