diff options
author | Matias Bjørling <m@bjorling.me> | 2016-01-12 01:49:21 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-01-12 10:21:16 -0500 |
commit | 91276162de9476b8ff32d9452e849210e5dd09e9 (patch) | |
tree | 53337c60f7d863b1ab733f9bcd4964da818f9057 | |
parent | abd805ec9f51f37db9da63dda44c3f4b4ae8ad57 (diff) |
lightnvm: refactor end_io functions for sync
To implement sync I/O support within the LightNVM core, the end_io
functions are refactored to take an end_io function pointer instead of
testing for initialized media manager, followed by calling its end_io
function.
Sync I/O can then be implemented using a callback that signal I/O
completion. This is similar to the logic found in blk_to_execute_io().
By implementing it this way, the underlying device I/Os submission logic
is abstracted away from core, targets, and media managers.
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/null_blk.c | 3 | ||||
-rw-r--r-- | drivers/lightnvm/core.c | 16 | ||||
-rw-r--r-- | drivers/lightnvm/gennvm.c | 34 | ||||
-rw-r--r-- | drivers/lightnvm/rrpc.c | 6 | ||||
-rw-r--r-- | drivers/nvme/host/lightnvm.c | 5 | ||||
-rw-r--r-- | include/linux/lightnvm.h | 12 |
6 files changed, 42 insertions, 34 deletions
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 09e3c0d87ecc..e6cad40a248f 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c | |||
@@ -436,9 +436,8 @@ static void null_del_dev(struct nullb *nullb) | |||
436 | static void null_lnvm_end_io(struct request *rq, int error) | 436 | static void null_lnvm_end_io(struct request *rq, int error) |
437 | { | 437 | { |
438 | struct nvm_rq *rqd = rq->end_io_data; | 438 | struct nvm_rq *rqd = rq->end_io_data; |
439 | struct nvm_dev *dev = rqd->dev; | ||
440 | 439 | ||
441 | dev->mt->end_io(rqd, error); | 440 | nvm_end_io(rqd, error); |
442 | 441 | ||
443 | blk_put_request(rq); | 442 | blk_put_request(rq); |
444 | } | 443 | } |
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 081b0f59b773..fa1a052c4737 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/miscdevice.h> | 28 | #include <linux/miscdevice.h> |
29 | #include <linux/lightnvm.h> | 29 | #include <linux/lightnvm.h> |
30 | #include <linux/sched/sysctl.h> | ||
30 | #include <uapi/linux/lightnvm.h> | 31 | #include <uapi/linux/lightnvm.h> |
31 | 32 | ||
32 | static LIST_HEAD(nvm_targets); | 33 | static LIST_HEAD(nvm_targets); |
@@ -288,6 +289,21 @@ int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr ppa) | |||
288 | } | 289 | } |
289 | EXPORT_SYMBOL(nvm_erase_ppa); | 290 | EXPORT_SYMBOL(nvm_erase_ppa); |
290 | 291 | ||
292 | void nvm_end_io(struct nvm_rq *rqd, int error) | ||
293 | { | ||
294 | rqd->end_io(rqd, error); | ||
295 | } | ||
296 | EXPORT_SYMBOL(nvm_end_io); | ||
297 | |||
298 | static void nvm_end_io_sync(struct nvm_rq *rqd, int errors) | ||
299 | { | ||
300 | struct completion *waiting = rqd->wait; | ||
301 | |||
302 | rqd->wait = NULL; | ||
303 | |||
304 | complete(waiting); | ||
305 | } | ||
306 | |||
291 | static int nvm_core_init(struct nvm_dev *dev) | 307 | static int nvm_core_init(struct nvm_dev *dev) |
292 | { | 308 | { |
293 | struct nvm_id *id = &dev->identity; | 309 | struct nvm_id *id = &dev->identity; |
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 373be72816bd..12ddcaa343e9 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c | |||
@@ -317,18 +317,6 @@ static void gennvm_put_blk(struct nvm_dev *dev, struct nvm_block *blk) | |||
317 | spin_unlock(&vlun->lock); | 317 | spin_unlock(&vlun->lock); |
318 | } | 318 | } |
319 | 319 | ||
320 | static int gennvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) | ||
321 | { | ||
322 | if (!dev->ops->submit_io) | ||
323 | return -ENODEV; | ||
324 | |||
325 | /* Convert address space */ | ||
326 | nvm_generic_to_addr_mode(dev, rqd); | ||
327 | |||
328 | rqd->dev = dev; | ||
329 | return dev->ops->submit_io(dev, rqd); | ||
330 | } | ||
331 | |||
332 | static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa, | 320 | static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa, |
333 | int type) | 321 | int type) |
334 | { | 322 | { |
@@ -375,25 +363,32 @@ static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd) | |||
375 | gennvm_blk_set_type(dev, &rqd->ppa_addr, 2); | 363 | gennvm_blk_set_type(dev, &rqd->ppa_addr, 2); |
376 | } | 364 | } |
377 | 365 | ||
378 | static int gennvm_end_io(struct nvm_rq *rqd, int error) | 366 | static void gennvm_end_io(struct nvm_rq *rqd, int error) |
379 | { | 367 | { |
380 | struct nvm_tgt_instance *ins = rqd->ins; | 368 | struct nvm_tgt_instance *ins = rqd->ins; |
381 | int ret = 0; | ||
382 | 369 | ||
383 | switch (error) { | 370 | switch (error) { |
384 | case NVM_RSP_SUCCESS: | 371 | case NVM_RSP_SUCCESS: |
385 | break; | ||
386 | case NVM_RSP_ERR_EMPTYPAGE: | 372 | case NVM_RSP_ERR_EMPTYPAGE: |
387 | break; | 373 | break; |
388 | case NVM_RSP_ERR_FAILWRITE: | 374 | case NVM_RSP_ERR_FAILWRITE: |
389 | gennvm_mark_blk_bad(rqd->dev, rqd); | 375 | gennvm_mark_blk_bad(rqd->dev, rqd); |
390 | default: | ||
391 | ret++; | ||
392 | } | 376 | } |
393 | 377 | ||
394 | ret += ins->tt->end_io(rqd, error); | 378 | ins->tt->end_io(rqd, error); |
379 | } | ||
395 | 380 | ||
396 | return ret; | 381 | static int gennvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) |
382 | { | ||
383 | if (!dev->ops->submit_io) | ||
384 | return -ENODEV; | ||
385 | |||
386 | /* Convert address space */ | ||
387 | nvm_generic_to_addr_mode(dev, rqd); | ||
388 | |||
389 | rqd->dev = dev; | ||
390 | rqd->end_io = gennvm_end_io; | ||
391 | return dev->ops->submit_io(dev, rqd); | ||
397 | } | 392 | } |
398 | 393 | ||
399 | static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk, | 394 | static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk, |
@@ -442,7 +437,6 @@ static struct nvmm_type gennvm = { | |||
442 | .put_blk = gennvm_put_blk, | 437 | .put_blk = gennvm_put_blk, |
443 | 438 | ||
444 | .submit_io = gennvm_submit_io, | 439 | .submit_io = gennvm_submit_io, |
445 | .end_io = gennvm_end_io, | ||
446 | .erase_blk = gennvm_erase_blk, | 440 | .erase_blk = gennvm_erase_blk, |
447 | 441 | ||
448 | .get_lun = gennvm_get_lun, | 442 | .get_lun = gennvm_get_lun, |
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 748cab499580..661c6f370f5a 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c | |||
@@ -642,7 +642,7 @@ static void rrpc_end_io_write(struct rrpc *rrpc, struct rrpc_rq *rrqd, | |||
642 | } | 642 | } |
643 | } | 643 | } |
644 | 644 | ||
645 | static int rrpc_end_io(struct nvm_rq *rqd, int error) | 645 | static void rrpc_end_io(struct nvm_rq *rqd, int error) |
646 | { | 646 | { |
647 | struct rrpc *rrpc = container_of(rqd->ins, struct rrpc, instance); | 647 | struct rrpc *rrpc = container_of(rqd->ins, struct rrpc, instance); |
648 | struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd); | 648 | struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd); |
@@ -655,7 +655,7 @@ static int rrpc_end_io(struct nvm_rq *rqd, int error) | |||
655 | bio_put(rqd->bio); | 655 | bio_put(rqd->bio); |
656 | 656 | ||
657 | if (rrqd->flags & NVM_IOTYPE_GC) | 657 | if (rrqd->flags & NVM_IOTYPE_GC) |
658 | return 0; | 658 | return; |
659 | 659 | ||
660 | rrpc_unlock_rq(rrpc, rqd); | 660 | rrpc_unlock_rq(rrpc, rqd); |
661 | 661 | ||
@@ -665,8 +665,6 @@ static int rrpc_end_io(struct nvm_rq *rqd, int error) | |||
665 | nvm_dev_dma_free(rrpc->dev, rqd->metadata, rqd->dma_metadata); | 665 | nvm_dev_dma_free(rrpc->dev, rqd->metadata, rqd->dma_metadata); |
666 | 666 | ||
667 | mempool_free(rqd, rrpc->rq_pool); | 667 | mempool_free(rqd, rrpc->rq_pool); |
668 | |||
669 | return 0; | ||
670 | } | 668 | } |
671 | 669 | ||
672 | static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio, | 670 | static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio, |
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 15f2acb4d5cd..1d1830e2ee10 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c | |||
@@ -453,11 +453,8 @@ static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd, | |||
453 | static void nvme_nvm_end_io(struct request *rq, int error) | 453 | static void nvme_nvm_end_io(struct request *rq, int error) |
454 | { | 454 | { |
455 | struct nvm_rq *rqd = rq->end_io_data; | 455 | struct nvm_rq *rqd = rq->end_io_data; |
456 | struct nvm_dev *dev = rqd->dev; | ||
457 | 456 | ||
458 | if (dev->mt && dev->mt->end_io(rqd, error)) | 457 | nvm_end_io(rqd, error); |
459 | pr_err("nvme: err status: %x result: %lx\n", | ||
460 | rq->errors, (unsigned long)rq->special); | ||
461 | 458 | ||
462 | kfree(rq->cmd); | 459 | kfree(rq->cmd); |
463 | blk_mq_free_request(rq); | 460 | blk_mq_free_request(rq); |
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 2fd6871ac7f5..9c9fe9ca0441 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h | |||
@@ -148,6 +148,9 @@ struct ppa_addr { | |||
148 | }; | 148 | }; |
149 | }; | 149 | }; |
150 | 150 | ||
151 | struct nvm_rq; | ||
152 | typedef void (nvm_end_io_fn)(struct nvm_rq *, int); | ||
153 | |||
151 | struct nvm_rq { | 154 | struct nvm_rq { |
152 | struct nvm_tgt_instance *ins; | 155 | struct nvm_tgt_instance *ins; |
153 | struct nvm_dev *dev; | 156 | struct nvm_dev *dev; |
@@ -164,6 +167,9 @@ struct nvm_rq { | |||
164 | void *metadata; | 167 | void *metadata; |
165 | dma_addr_t dma_metadata; | 168 | dma_addr_t dma_metadata; |
166 | 169 | ||
170 | struct completion *wait; | ||
171 | nvm_end_io_fn *end_io; | ||
172 | |||
167 | uint8_t opcode; | 173 | uint8_t opcode; |
168 | uint16_t nr_pages; | 174 | uint16_t nr_pages; |
169 | uint16_t flags; | 175 | uint16_t flags; |
@@ -347,7 +353,6 @@ static inline struct ppa_addr block_to_ppa(struct nvm_dev *dev, | |||
347 | 353 | ||
348 | typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *); | 354 | typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *); |
349 | typedef sector_t (nvm_tgt_capacity_fn)(void *); | 355 | typedef sector_t (nvm_tgt_capacity_fn)(void *); |
350 | typedef int (nvm_tgt_end_io_fn)(struct nvm_rq *, int); | ||
351 | typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int); | 356 | typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int); |
352 | typedef void (nvm_tgt_exit_fn)(void *); | 357 | typedef void (nvm_tgt_exit_fn)(void *); |
353 | 358 | ||
@@ -358,7 +363,7 @@ struct nvm_tgt_type { | |||
358 | /* target entry points */ | 363 | /* target entry points */ |
359 | nvm_tgt_make_rq_fn *make_rq; | 364 | nvm_tgt_make_rq_fn *make_rq; |
360 | nvm_tgt_capacity_fn *capacity; | 365 | nvm_tgt_capacity_fn *capacity; |
361 | nvm_tgt_end_io_fn *end_io; | 366 | nvm_end_io_fn *end_io; |
362 | 367 | ||
363 | /* module-specific init/teardown */ | 368 | /* module-specific init/teardown */ |
364 | nvm_tgt_init_fn *init; | 369 | nvm_tgt_init_fn *init; |
@@ -383,7 +388,6 @@ typedef int (nvmm_open_blk_fn)(struct nvm_dev *, struct nvm_block *); | |||
383 | typedef int (nvmm_close_blk_fn)(struct nvm_dev *, struct nvm_block *); | 388 | typedef int (nvmm_close_blk_fn)(struct nvm_dev *, struct nvm_block *); |
384 | typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *); | 389 | typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *); |
385 | typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); | 390 | typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); |
386 | typedef int (nvmm_end_io_fn)(struct nvm_rq *, int); | ||
387 | typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, | 391 | typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, |
388 | unsigned long); | 392 | unsigned long); |
389 | typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); | 393 | typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); |
@@ -404,7 +408,6 @@ struct nvmm_type { | |||
404 | nvmm_flush_blk_fn *flush_blk; | 408 | nvmm_flush_blk_fn *flush_blk; |
405 | 409 | ||
406 | nvmm_submit_io_fn *submit_io; | 410 | nvmm_submit_io_fn *submit_io; |
407 | nvmm_end_io_fn *end_io; | ||
408 | nvmm_erase_blk_fn *erase_blk; | 411 | nvmm_erase_blk_fn *erase_blk; |
409 | 412 | ||
410 | /* Configuration management */ | 413 | /* Configuration management */ |
@@ -434,6 +437,7 @@ extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *, | |||
434 | extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); | 437 | extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); |
435 | extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr); | 438 | extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr); |
436 | extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); | 439 | extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); |
440 | extern void nvm_end_io(struct nvm_rq *, int); | ||
437 | #else /* CONFIG_NVM */ | 441 | #else /* CONFIG_NVM */ |
438 | struct nvm_dev_ops; | 442 | struct nvm_dev_ops; |
439 | 443 | ||