Add a target to print its debug information when lightnvm debug
information is printed trough configure_debug.

In rrpc, we add statistics on inflight reads and writes, as well as
submitted and synced writes.

Signed-off-by: Javier González <jav...@cnexlabs.com>
---
 drivers/lightnvm/core.c  | 10 +++++++++
 drivers/lightnvm/rrpc.c  | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/lightnvm/rrpc.h  |  8 +++++++
 include/linux/lightnvm.h |  4 ++++
 4 files changed, 79 insertions(+)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 5471cc5..ef64243 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -771,6 +771,8 @@ static int __nvm_configure_remove(struct nvm_ioctl_remove 
*remove)
 static int nvm_configure_show(const char *val)
 {
        struct nvm_dev *dev;
+       struct nvm_target *t = NULL;
+       struct nvm_tgt_type *tt;
        char opcode, devname[DISK_NAME_LEN];
        int ret;
 
@@ -793,6 +795,14 @@ static int nvm_configure_show(const char *val)
 
        dev->mt->lun_info_print(dev);
 
+       down_write(&nvm_lock);
+       list_for_each_entry(dev, &nvm_devices, devices)
+               list_for_each_entry(t, &dev->online_targets, list) {
+                       tt = t->type;
+                       tt->print_debug(t->disk->private_data);
+               }
+       up_write(&nvm_lock);
+
        return 0;
 }
 
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 6348d52..41bd9b0 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -784,6 +784,11 @@ static void rrpc_sync_buffer(struct rrpc *rrpc, struct 
rrpc_addr *p)
 
        WARN_ON(test_and_set_bit((p->addr - bppa), buf->sync_bitmap));
 
+#ifdef CONFIG_NVM_DEBUG
+               atomic_dec(&rrpc->inflight_writes);
+               atomic_inc(&rrpc->sync_writes);
+#endif
+
        if (unlikely(bitmap_full(buf->sync_bitmap, buf->nentries))) {
                /* Write buffer out-of-bounds */
                WARN_ON((buf->cur_mem != buf->nentries) &&
@@ -820,6 +825,9 @@ static void rrpc_end_io_read(struct rrpc *rrpc, struct 
nvm_rq *rqd,
 
        rrpc_unlock_rq(rrpc, rrqd);
        mempool_free(rrqd, rrpc->rrq_pool);
+#ifdef CONFIG_NVM_DEBUG
+       atomic_sub(nr_pages, &rrpc->inflight_reads);
+#endif
 }
 
 static void rrpc_end_io(struct nvm_rq *rqd)
@@ -919,6 +927,11 @@ static int rrpc_write_ppalist_rq(struct rrpc *rrpc, struct 
bio *bio,
 
                rrqd->addr = p;
 
+#ifdef CONFIG_NVM_DEBUG
+               atomic_inc(&rrpc->inflight_writes);
+               atomic_inc(&rrpc->req_writes);
+#endif
+
                err = rrpc_write_to_buffer(rrpc, bio, rrqd, p, w_buf, flags);
                if (err) {
                        pr_err("rrpc: could not write to write buffer\n");
@@ -967,6 +980,11 @@ static int rrpc_write_rq(struct rrpc *rrpc, struct bio 
*bio,
 
        rrqd->addr = p;
 
+#ifdef CONFIG_NVM_DEBUG
+       atomic_inc(&rrpc->inflight_writes);
+       atomic_inc(&rrpc->req_writes);
+#endif
+
        err = rrpc_write_to_buffer(rrpc, bio, rrqd, p, w_buf, flags);
        if (err) {
                pr_err("rrpc: could not write to write buffer\n");
@@ -1023,6 +1041,10 @@ static int rrpc_read_ppalist_rq(struct rrpc *rrpc, 
struct bio *bio,
                }
 
                brrqd[i].addr = gp;
+
+#ifdef CONFIG_NVM_DEBUG
+               atomic_inc(&rrpc->inflight_reads);
+#endif
        }
 
        rqd->opcode = NVM_OP_HBREAD;
@@ -1055,6 +1077,10 @@ static int rrpc_read_rq(struct rrpc *rrpc, struct bio 
*bio, struct nvm_rq *rqd,
        rqd->opcode = NVM_OP_HBREAD;
        rrqd->addr = gp;
 
+#ifdef CONFIG_NVM_DEBUG
+               atomic_inc(&rrpc->inflight_reads);
+#endif
+
        return NVM_IO_OK;
 }
 
@@ -1615,6 +1641,9 @@ submit_io:
                        mempool_free(rqd, rrpc->rq_pool);
                        bio_put(bio);
                }
+#ifdef CONFIG_NVM_DEBUG
+               atomic_add(pgs_to_sync, &rrpc->sub_writes);
+#endif
        }
 
        spin_unlock(&rlun->parent->lock);
@@ -2128,6 +2157,14 @@ static void *rrpc_init(struct nvm_dev *dev, struct 
gendisk *tdisk,
        /* simple round-robin strategy */
        atomic_set(&rrpc->next_lun, -1);
 
+#ifdef CONFIG_NVM_DEBUG
+       atomic_set(&rrpc->inflight_writes, 0);
+       atomic_set(&rrpc->req_writes, 0);
+       atomic_set(&rrpc->sub_writes, 0);
+       atomic_set(&rrpc->sync_writes, 0);
+       atomic_set(&rrpc->inflight_reads, 0);
+#endif
+
        ret = rrpc_luns_init(rrpc, lun_begin, lun_end);
        if (ret) {
                pr_err("nvm: rrpc: could not initialize luns\n");
@@ -2182,6 +2219,24 @@ err:
        return ERR_PTR(ret);
 }
 
+#ifdef CONFIG_NVM_DEBUG
+static void rrpc_print_debug(void *private)
+{
+       struct rrpc *rrpc = private;
+
+       pr_info("rrpc: %u\t%u\t%u\t%u\t%u\n",
+                               atomic_read(&rrpc->inflight_writes),
+                               atomic_read(&rrpc->inflight_reads),
+                               atomic_read(&rrpc->req_writes),
+                               atomic_read(&rrpc->sub_writes),
+                               atomic_read(&rrpc->sync_writes));
+}
+#else
+static void rrpc_print_debug(void *private)
+{
+}
+#endif
+
 /* round robin, page-based FTL, and cost-based GC */
 static struct nvm_tgt_type tt_rrpc = {
        .name           = "rrpc",
@@ -2193,6 +2248,8 @@ static struct nvm_tgt_type tt_rrpc = {
 
        .init           = rrpc_init,
        .exit           = rrpc_exit,
+
+       .print_debug    = rrpc_print_debug,
 };
 
 static int __init rrpc_module_init(void)
diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h
index 6e188b4..b7c40de 100644
--- a/drivers/lightnvm/rrpc.h
+++ b/drivers/lightnvm/rrpc.h
@@ -167,6 +167,14 @@ struct rrpc {
                            * to point to the next write lun
                            */
 
+#ifdef CONFIG_NVM_DEBUG
+       atomic_t inflight_writes;
+       atomic_t req_writes;
+       atomic_t sub_writes;
+       atomic_t sync_writes;
+       atomic_t inflight_reads;
+#endif
+
        spinlock_t bio_lock;
        struct bio_list requeue_bios;
        struct work_struct ws_requeue;
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index ae26ced..12a4296 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -428,6 +428,7 @@ typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue 
*, struct bio *);
 typedef sector_t (nvm_tgt_capacity_fn)(void *);
 typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int);
 typedef void (nvm_tgt_exit_fn)(void *);
+typedef void (nvm_tgt_print_debug_fn)(void *);
 
 struct nvm_tgt_type {
        const char *name;
@@ -442,6 +443,9 @@ struct nvm_tgt_type {
        nvm_tgt_init_fn *init;
        nvm_tgt_exit_fn *exit;
 
+       /* debugging */
+       nvm_tgt_print_debug_fn *print_debug;
+
        /* For internal use */
        struct list_head list;
 };
-- 
2.1.4

Reply via email to