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