summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatias Bjørling <m@bjorling.me>2016-01-12 01:49:21 -0500
committerJens Axboe <axboe@fb.com>2016-01-12 10:21:16 -0500
commit91276162de9476b8ff32d9452e849210e5dd09e9 (patch)
tree53337c60f7d863b1ab733f9bcd4964da818f9057
parentabd805ec9f51f37db9da63dda44c3f4b4ae8ad57 (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.c3
-rw-r--r--drivers/lightnvm/core.c16
-rw-r--r--drivers/lightnvm/gennvm.c34
-rw-r--r--drivers/lightnvm/rrpc.c6
-rw-r--r--drivers/nvme/host/lightnvm.c5
-rw-r--r--include/linux/lightnvm.h12
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)
436static void null_lnvm_end_io(struct request *rq, int error) 436static 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
32static LIST_HEAD(nvm_targets); 33static LIST_HEAD(nvm_targets);
@@ -288,6 +289,21 @@ int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr ppa)
288} 289}
289EXPORT_SYMBOL(nvm_erase_ppa); 290EXPORT_SYMBOL(nvm_erase_ppa);
290 291
292void nvm_end_io(struct nvm_rq *rqd, int error)
293{
294 rqd->end_io(rqd, error);
295}
296EXPORT_SYMBOL(nvm_end_io);
297
298static 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
291static int nvm_core_init(struct nvm_dev *dev) 307static 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
320static 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
332static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa, 320static 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
378static int gennvm_end_io(struct nvm_rq *rqd, int error) 366static 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; 381static 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
399static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk, 394static 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
645static int rrpc_end_io(struct nvm_rq *rqd, int error) 645static 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
672static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio, 670static 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,
453static void nvme_nvm_end_io(struct request *rq, int error) 453static 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
151struct nvm_rq;
152typedef void (nvm_end_io_fn)(struct nvm_rq *, int);
153
151struct nvm_rq { 154struct 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
348typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *); 354typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *);
349typedef sector_t (nvm_tgt_capacity_fn)(void *); 355typedef sector_t (nvm_tgt_capacity_fn)(void *);
350typedef int (nvm_tgt_end_io_fn)(struct nvm_rq *, int);
351typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int); 356typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int);
352typedef void (nvm_tgt_exit_fn)(void *); 357typedef 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 *);
383typedef int (nvmm_close_blk_fn)(struct nvm_dev *, struct nvm_block *); 388typedef int (nvmm_close_blk_fn)(struct nvm_dev *, struct nvm_block *);
384typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *); 389typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *);
385typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); 390typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
386typedef int (nvmm_end_io_fn)(struct nvm_rq *, int);
387typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, 391typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *,
388 unsigned long); 392 unsigned long);
389typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); 393typedef 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 *,
434extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); 437extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *);
435extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr); 438extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr);
436extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); 439extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *);
440extern void nvm_end_io(struct nvm_rq *, int);
437#else /* CONFIG_NVM */ 441#else /* CONFIG_NVM */
438struct nvm_dev_ops; 442struct nvm_dev_ops;
439 443