diff mbox

[RFC,4/4] lightnvm: add debug info for rrpc target

Message ID 1454591299-30305-5-git-send-email-javier@javigon.com (mailing list archive)
State New, archived
Headers show

Commit Message

=?UTF-8?q?Javier=20Gonz=C3=A1lez?= Feb. 4, 2016, 1:08 p.m. UTC
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 <javier@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 mbox

Patch

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;
 };