All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 6/6] lightnvm: expose gennvm target type through sysfs
@ 2016-06-10 12:22 ` Matias Bjørling
  0 siblings, 0 replies; 6+ messages in thread
From: Matias Bjørling @ 2016-06-10 12:22 UTC (permalink / raw)
  To: linux-block, linux-kernel, axboe, keith.busch, linux-nvme
  Cc: Simon A. F. Lund, Matias Bjørling

From: "Simon A. F. Lund" <slund@cnexlabs.com>

Create a sysfs directory for targets to expose their internal statistics
and knobs. The entries is exposed through the
/sys/block/<disk>/lightnvm/* directory.

It currently holds a single sysfs entry "type", which exports the target
type name.

Signed-off-by: Simon A. F. Lund <slund@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
---
 drivers/lightnvm/gennvm.c | 112 ++++++++++++++++++++++++++++++++++++++--------
 include/linux/lightnvm.h  |  10 +++++
 2 files changed, 104 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index b74174c..bfdad3c 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -20,6 +20,87 @@
 
 #include "gennvm.h"
 
+static struct attribute gen_type_attr = {
+	.name = "type",
+	.mode = S_IRUGO
+};
+
+static struct attribute *gen_target_attrs[] = {
+	&gen_type_attr,
+	NULL,
+};
+
+static ssize_t gen_target_attr_show(struct kobject *kobj,
+				struct attribute *attr,
+				char *page)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+
+	if (strcmp(attr->name, "type") == 0)
+		return scnprintf(page, PAGE_SIZE, "%s\n", t->type->name);
+
+	if (t->type->sysfs_show)
+		return t->type->sysfs_show(t, attr, page);
+
+	return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_target_attr_show`\n",
+			attr->name);
+}
+
+static const struct sysfs_ops target_sysfs_ops = {
+	.show = gen_target_attr_show,
+};
+
+static void gen_target_release(struct kobject *kobj)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+	struct nvm_tgt_type *tt = t->type;
+	struct gendisk *tdisk = t->disk;
+	struct request_queue *q = tdisk->queue;
+
+	pr_debug("gen: `gen_target_release`\n");
+
+	del_gendisk(tdisk);
+	blk_cleanup_queue(q);
+	put_disk(tdisk);
+
+	if (tt->exit)
+		tt->exit(tdisk->private_data);
+
+	kfree(t);
+}
+
+static struct kobj_type nvm_target_type = {
+	.sysfs_ops	= &target_sysfs_ops,
+	.default_attrs	= gen_target_attrs,
+	.release	= gen_target_release
+};
+
+void gen_unregister_target(struct nvm_target *t)
+{
+	kobject_uevent(&t->kobj, KOBJ_REMOVE);
+	kobject_del(&t->kobj);
+	kobject_put(&t->kobj);
+}
+
+int gen_register_target(struct nvm_target *t)
+{
+	struct gendisk *disk = t->disk;
+	struct device *dev = disk_to_dev(disk);
+	int ret;
+
+	ret = kobject_init_and_add(&t->kobj, &nvm_target_type,
+				   kobject_get(&dev->kobj), "%s", "lightnvm");
+	if (ret < 0) {
+		pr_err("gen: `_register_target` failed.\n");
+		kobject_put(&t->kobj);
+		return ret;
+	}
+
+	kobject_uevent(&t->kobj, KOBJ_ADD);
+	return 0;
+}
+
 static struct nvm_target *gen_find_target(struct gen_dev *gn, const char *name)
 {
 	struct nvm_target *tgt;
@@ -60,7 +141,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	}
 	mutex_unlock(&gn->lock);
 
-	t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
+	t = kzalloc(sizeof(struct nvm_target), GFP_KERNEL);
 	if (!t)
 		return -ENOMEM;
 
@@ -89,13 +170,19 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 
 	blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
 
-	set_capacity(tdisk, tt->capacity(targetdata));
-	add_disk(tdisk);
-
 	t->type = tt;
 	t->disk = tdisk;
 	t->dev = dev;
 
+	set_capacity(tdisk, tt->capacity(targetdata));
+	add_disk(tdisk);
+
+	if (gen_register_target(t))
+		goto err_init;
+
+	if (tt->sysfs_init)
+		tt->sysfs_init(t);
+
 	mutex_lock(&gn->lock);
 	list_add_tail(&t->list, &gn->targets);
 	mutex_unlock(&gn->lock);
@@ -112,20 +199,10 @@ err_t:
 
 static void __gen_remove_target(struct nvm_target *t)
 {
-	struct nvm_tgt_type *tt = t->type;
-	struct gendisk *tdisk = t->disk;
-	struct request_queue *q = tdisk->queue;
-
-	del_gendisk(tdisk);
-	blk_cleanup_queue(q);
-
-	if (tt->exit)
-		tt->exit(tdisk->private_data);
-
-	put_disk(tdisk);
-
 	list_del(&t->list);
-	kfree(t);
+	if (t->type->sysfs_exit)
+		t->type->sysfs_exit(t);
+	gen_unregister_target(t);
 }
 
 /**
@@ -627,7 +704,6 @@ static void gen_lun_info_print(struct nvm_dev *dev)
 	struct gen_lun *lun;
 	unsigned int i;
 
-
 	gen_for_each_lun(gn, lun, i) {
 		spin_lock(&lun->vlun.lock);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index d190786..3823891 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -211,6 +211,8 @@ struct nvm_target {
 	struct nvm_dev *dev;
 	struct nvm_tgt_type *type;
 	struct gendisk *disk;
+
+	struct kobject kobj;
 };
 
 struct nvm_tgt_instance {
@@ -434,6 +436,10 @@ 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_sysfs_init_fn)(struct nvm_target *);
+typedef void (nvm_tgt_sysfs_exit_fn)(struct nvm_target *);
+typedef ssize_t(nvm_tgt_sysfs_show_fn)(struct nvm_target *,
+				     struct attribute *, char *);
 
 struct nvm_tgt_type {
 	const char *name;
@@ -448,6 +454,10 @@ struct nvm_tgt_type {
 	nvm_tgt_init_fn *init;
 	nvm_tgt_exit_fn *exit;
 
+	nvm_tgt_sysfs_init_fn *sysfs_init;
+	nvm_tgt_sysfs_exit_fn *sysfs_exit;
+	nvm_tgt_sysfs_show_fn *sysfs_show;
+
 	/* For internal use */
 	struct list_head list;
 };
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] lightnvm: expose gennvm target type through sysfs
@ 2016-06-10 12:22 ` Matias Bjørling
  0 siblings, 0 replies; 6+ messages in thread
From: Matias Bjørling @ 2016-06-10 12:22 UTC (permalink / raw)


From: "Simon A. F. Lund" <slund@cnexlabs.com>

Create a sysfs directory for targets to expose their internal statistics
and knobs. The entries is exposed through the
/sys/block/<disk>/lightnvm/* directory.

It currently holds a single sysfs entry "type", which exports the target
type name.

Signed-off-by: Simon A. F. Lund <slund at cnexlabs.com>
Signed-off-by: Matias Bj?rling <m at bjorling.me>
---
 drivers/lightnvm/gennvm.c | 112 ++++++++++++++++++++++++++++++++++++++--------
 include/linux/lightnvm.h  |  10 +++++
 2 files changed, 104 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index b74174c..bfdad3c 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -20,6 +20,87 @@
 
 #include "gennvm.h"
 
+static struct attribute gen_type_attr = {
+	.name = "type",
+	.mode = S_IRUGO
+};
+
+static struct attribute *gen_target_attrs[] = {
+	&gen_type_attr,
+	NULL,
+};
+
+static ssize_t gen_target_attr_show(struct kobject *kobj,
+				struct attribute *attr,
+				char *page)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+
+	if (strcmp(attr->name, "type") == 0)
+		return scnprintf(page, PAGE_SIZE, "%s\n", t->type->name);
+
+	if (t->type->sysfs_show)
+		return t->type->sysfs_show(t, attr, page);
+
+	return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_target_attr_show`\n",
+			attr->name);
+}
+
+static const struct sysfs_ops target_sysfs_ops = {
+	.show = gen_target_attr_show,
+};
+
+static void gen_target_release(struct kobject *kobj)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+	struct nvm_tgt_type *tt = t->type;
+	struct gendisk *tdisk = t->disk;
+	struct request_queue *q = tdisk->queue;
+
+	pr_debug("gen: `gen_target_release`\n");
+
+	del_gendisk(tdisk);
+	blk_cleanup_queue(q);
+	put_disk(tdisk);
+
+	if (tt->exit)
+		tt->exit(tdisk->private_data);
+
+	kfree(t);
+}
+
+static struct kobj_type nvm_target_type = {
+	.sysfs_ops	= &target_sysfs_ops,
+	.default_attrs	= gen_target_attrs,
+	.release	= gen_target_release
+};
+
+void gen_unregister_target(struct nvm_target *t)
+{
+	kobject_uevent(&t->kobj, KOBJ_REMOVE);
+	kobject_del(&t->kobj);
+	kobject_put(&t->kobj);
+}
+
+int gen_register_target(struct nvm_target *t)
+{
+	struct gendisk *disk = t->disk;
+	struct device *dev = disk_to_dev(disk);
+	int ret;
+
+	ret = kobject_init_and_add(&t->kobj, &nvm_target_type,
+				   kobject_get(&dev->kobj), "%s", "lightnvm");
+	if (ret < 0) {
+		pr_err("gen: `_register_target` failed.\n");
+		kobject_put(&t->kobj);
+		return ret;
+	}
+
+	kobject_uevent(&t->kobj, KOBJ_ADD);
+	return 0;
+}
+
 static struct nvm_target *gen_find_target(struct gen_dev *gn, const char *name)
 {
 	struct nvm_target *tgt;
@@ -60,7 +141,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	}
 	mutex_unlock(&gn->lock);
 
-	t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
+	t = kzalloc(sizeof(struct nvm_target), GFP_KERNEL);
 	if (!t)
 		return -ENOMEM;
 
@@ -89,13 +170,19 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 
 	blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
 
-	set_capacity(tdisk, tt->capacity(targetdata));
-	add_disk(tdisk);
-
 	t->type = tt;
 	t->disk = tdisk;
 	t->dev = dev;
 
+	set_capacity(tdisk, tt->capacity(targetdata));
+	add_disk(tdisk);
+
+	if (gen_register_target(t))
+		goto err_init;
+
+	if (tt->sysfs_init)
+		tt->sysfs_init(t);
+
 	mutex_lock(&gn->lock);
 	list_add_tail(&t->list, &gn->targets);
 	mutex_unlock(&gn->lock);
@@ -112,20 +199,10 @@ err_t:
 
 static void __gen_remove_target(struct nvm_target *t)
 {
-	struct nvm_tgt_type *tt = t->type;
-	struct gendisk *tdisk = t->disk;
-	struct request_queue *q = tdisk->queue;
-
-	del_gendisk(tdisk);
-	blk_cleanup_queue(q);
-
-	if (tt->exit)
-		tt->exit(tdisk->private_data);
-
-	put_disk(tdisk);
-
 	list_del(&t->list);
-	kfree(t);
+	if (t->type->sysfs_exit)
+		t->type->sysfs_exit(t);
+	gen_unregister_target(t);
 }
 
 /**
@@ -627,7 +704,6 @@ static void gen_lun_info_print(struct nvm_dev *dev)
 	struct gen_lun *lun;
 	unsigned int i;
 
-
 	gen_for_each_lun(gn, lun, i) {
 		spin_lock(&lun->vlun.lock);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index d190786..3823891 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -211,6 +211,8 @@ struct nvm_target {
 	struct nvm_dev *dev;
 	struct nvm_tgt_type *type;
 	struct gendisk *disk;
+
+	struct kobject kobj;
 };
 
 struct nvm_tgt_instance {
@@ -434,6 +436,10 @@ 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_sysfs_init_fn)(struct nvm_target *);
+typedef void (nvm_tgt_sysfs_exit_fn)(struct nvm_target *);
+typedef ssize_t(nvm_tgt_sysfs_show_fn)(struct nvm_target *,
+				     struct attribute *, char *);
 
 struct nvm_tgt_type {
 	const char *name;
@@ -448,6 +454,10 @@ struct nvm_tgt_type {
 	nvm_tgt_init_fn *init;
 	nvm_tgt_exit_fn *exit;
 
+	nvm_tgt_sysfs_init_fn *sysfs_init;
+	nvm_tgt_sysfs_exit_fn *sysfs_exit;
+	nvm_tgt_sysfs_show_fn *sysfs_show;
+
 	/* For internal use */
 	struct list_head list;
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] lightnvm: expose gennvm target type through sysfs
  2016-06-29 14:51 [PATCH 0/6] enable sysfs for lightnvm Matias Bjørling
  2016-06-29 14:51   ` Matias Bjørling
  (?)
@ 2016-06-29 14:51   ` Matias Bjørling
  0 siblings, 0 replies; 6+ messages in thread
From: Matias Bjørling @ 2016-06-29 14:51 UTC (permalink / raw)
  To: linux-block, linux-kernel, axboe, keith.busch, linux-nvme, dm-devel
  Cc: Simon A. F. Lund, Matias Bjørling

RnJvbTogIlNpbW9uIEEuIEYuIEx1bmQiIDxzbHVuZEBjbmV4bGFicy5jb20+CgpDcmVhdGUgYSBz
eXNmcyBkaXJlY3RvcnkgZm9yIHRhcmdldHMgdG8gZXhwb3NlIHRoZWlyIGludGVybmFsIHN0YXRp
c3RpY3MKYW5kIGtub2JzLiBUaGUgZW50cmllcyBpcyBleHBvc2VkIHRocm91Z2ggdGhlCi9zeXMv
YmxvY2svPGRpc2s+L2xpZ2h0bnZtLyogZGlyZWN0b3J5LgoKSXQgY3VycmVudGx5IGhvbGRzIGEg
c2luZ2xlIHN5c2ZzIGVudHJ5ICJ0eXBlIiwgd2hpY2ggZXhwb3J0cyB0aGUgdGFyZ2V0CnR5cGUg
bmFtZS4KClNpZ25lZC1vZmYtYnk6IFNpbW9uIEEuIEYuIEx1bmQgPHNsdW5kQGNuZXhsYWJzLmNv
bT4KU2lnbmVkLW9mZi1ieTogTWF0aWFzIEJqw7hybGluZyA8bUBiam9ybGluZy5tZT4KLS0tCiBk
cml2ZXJzL2xpZ2h0bnZtL2dlbm52bS5jIHwgMTEyICsrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrLS0tLS0tLS0KIGluY2x1ZGUvbGludXgvbGlnaHRudm0uaCAgfCAgMTAgKysr
KysKIDIgZmlsZXMgY2hhbmdlZCwgMTA0IGluc2VydGlvbnMoKyksIDE4IGRlbGV0aW9ucygtKQoK
ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbGlnaHRudm0vZ2VubnZtLmMgYi9kcml2ZXJzL2xpZ2h0bnZt
L2dlbm52bS5jCmluZGV4IGI3NDE3NGMuLmJmZGFkM2MgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbGln
aHRudm0vZ2VubnZtLmMKKysrIGIvZHJpdmVycy9saWdodG52bS9nZW5udm0uYwpAQCAtMjAsNiAr
MjAsODcgQEAKIAogI2luY2x1ZGUgImdlbm52bS5oIgogCitzdGF0aWMgc3RydWN0IGF0dHJpYnV0
ZSBnZW5fdHlwZV9hdHRyID0geworCS5uYW1lID0gInR5cGUiLAorCS5tb2RlID0gU19JUlVHTwor
fTsKKworc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmdlbl90YXJnZXRfYXR0cnNbXSA9IHsKKwkm
Z2VuX3R5cGVfYXR0ciwKKwlOVUxMLAorfTsKKworc3RhdGljIHNzaXplX3QgZ2VuX3RhcmdldF9h
dHRyX3Nob3coc3RydWN0IGtvYmplY3QgKmtvYmosCisJCQkJc3RydWN0IGF0dHJpYnV0ZSAqYXR0
ciwKKwkJCQljaGFyICpwYWdlKQoreworCXN0cnVjdCBudm1fdGFyZ2V0ICp0ID0gY29udGFpbmVy
X29mKGtvYmosIHN0cnVjdCBudm1fdGFyZ2V0LCBrb2JqKTsKKworCWlmIChzdHJjbXAoYXR0ci0+
bmFtZSwgInR5cGUiKSA9PSAwKQorCQlyZXR1cm4gc2NucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwg
IiVzXG4iLCB0LT50eXBlLT5uYW1lKTsKKworCWlmICh0LT50eXBlLT5zeXNmc19zaG93KQorCQly
ZXR1cm4gdC0+dHlwZS0+c3lzZnNfc2hvdyh0LCBhdHRyLCBwYWdlKTsKKworCXJldHVybiBzY25w
cmludGYocGFnZSwgUEFHRV9TSVpFLAorCQkJIlVuaGFuZGxlZCBhdHRyKCVzKSBpbiBgbnZtX3Rh
cmdldF9hdHRyX3Nob3dgXG4iLAorCQkJYXR0ci0+bmFtZSk7Cit9CisKK3N0YXRpYyBjb25zdCBz
dHJ1Y3Qgc3lzZnNfb3BzIHRhcmdldF9zeXNmc19vcHMgPSB7CisJLnNob3cgPSBnZW5fdGFyZ2V0
X2F0dHJfc2hvdywKK307CisKK3N0YXRpYyB2b2lkIGdlbl90YXJnZXRfcmVsZWFzZShzdHJ1Y3Qg
a29iamVjdCAqa29iaikKK3sKKwlzdHJ1Y3QgbnZtX3RhcmdldCAqdCA9IGNvbnRhaW5lcl9vZihr
b2JqLCBzdHJ1Y3QgbnZtX3RhcmdldCwga29iaik7CisJc3RydWN0IG52bV90Z3RfdHlwZSAqdHQg
PSB0LT50eXBlOworCXN0cnVjdCBnZW5kaXNrICp0ZGlzayA9IHQtPmRpc2s7CisJc3RydWN0IHJl
cXVlc3RfcXVldWUgKnEgPSB0ZGlzay0+cXVldWU7CisKKwlwcl9kZWJ1ZygiZ2VuOiBgZ2VuX3Rh
cmdldF9yZWxlYXNlYFxuIik7CisKKwlkZWxfZ2VuZGlzayh0ZGlzayk7CisJYmxrX2NsZWFudXBf
cXVldWUocSk7CisJcHV0X2Rpc2sodGRpc2spOworCisJaWYgKHR0LT5leGl0KQorCQl0dC0+ZXhp
dCh0ZGlzay0+cHJpdmF0ZV9kYXRhKTsKKworCWtmcmVlKHQpOworfQorCitzdGF0aWMgc3RydWN0
IGtvYmpfdHlwZSBudm1fdGFyZ2V0X3R5cGUgPSB7CisJLnN5c2ZzX29wcwk9ICZ0YXJnZXRfc3lz
ZnNfb3BzLAorCS5kZWZhdWx0X2F0dHJzCT0gZ2VuX3RhcmdldF9hdHRycywKKwkucmVsZWFzZQk9
IGdlbl90YXJnZXRfcmVsZWFzZQorfTsKKwordm9pZCBnZW5fdW5yZWdpc3Rlcl90YXJnZXQoc3Ry
dWN0IG52bV90YXJnZXQgKnQpCit7CisJa29iamVjdF91ZXZlbnQoJnQtPmtvYmosIEtPQkpfUkVN
T1ZFKTsKKwlrb2JqZWN0X2RlbCgmdC0+a29iaik7CisJa29iamVjdF9wdXQoJnQtPmtvYmopOwor
fQorCitpbnQgZ2VuX3JlZ2lzdGVyX3RhcmdldChzdHJ1Y3QgbnZtX3RhcmdldCAqdCkKK3sKKwlz
dHJ1Y3QgZ2VuZGlzayAqZGlzayA9IHQtPmRpc2s7CisJc3RydWN0IGRldmljZSAqZGV2ID0gZGlz
a190b19kZXYoZGlzayk7CisJaW50IHJldDsKKworCXJldCA9IGtvYmplY3RfaW5pdF9hbmRfYWRk
KCZ0LT5rb2JqLCAmbnZtX3RhcmdldF90eXBlLAorCQkJCSAgIGtvYmplY3RfZ2V0KCZkZXYtPmtv
YmopLCAiJXMiLCAibGlnaHRudm0iKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcl9lcnIoImdlbjog
YF9yZWdpc3Rlcl90YXJnZXRgIGZhaWxlZC5cbiIpOworCQlrb2JqZWN0X3B1dCgmdC0+a29iaik7
CisJCXJldHVybiByZXQ7CisJfQorCisJa29iamVjdF91ZXZlbnQoJnQtPmtvYmosIEtPQkpfQURE
KTsKKwlyZXR1cm4gMDsKK30KKwogc3RhdGljIHN0cnVjdCBudm1fdGFyZ2V0ICpnZW5fZmluZF90
YXJnZXQoc3RydWN0IGdlbl9kZXYgKmduLCBjb25zdCBjaGFyICpuYW1lKQogewogCXN0cnVjdCBu
dm1fdGFyZ2V0ICp0Z3Q7CkBAIC02MCw3ICsxNDEsNyBAQCBzdGF0aWMgaW50IGdlbl9jcmVhdGVf
dGd0KHN0cnVjdCBudm1fZGV2ICpkZXYsIHN0cnVjdCBudm1faW9jdGxfY3JlYXRlICpjcmVhdGUp
CiAJfQogCW11dGV4X3VubG9jaygmZ24tPmxvY2spOwogCi0JdCA9IGttYWxsb2Moc2l6ZW9mKHN0
cnVjdCBudm1fdGFyZ2V0KSwgR0ZQX0tFUk5FTCk7CisJdCA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVj
dCBudm1fdGFyZ2V0KSwgR0ZQX0tFUk5FTCk7CiAJaWYgKCF0KQogCQlyZXR1cm4gLUVOT01FTTsK
IApAQCAtODksMTMgKzE3MCwxOSBAQCBzdGF0aWMgaW50IGdlbl9jcmVhdGVfdGd0KHN0cnVjdCBu
dm1fZGV2ICpkZXYsIHN0cnVjdCBudm1faW9jdGxfY3JlYXRlICpjcmVhdGUpCiAKIAlibGtfcXVl
dWVfbWF4X2h3X3NlY3RvcnModHF1ZXVlLCA4ICogZGV2LT5vcHMtPm1heF9waHlzX3NlY3QpOwog
Ci0Jc2V0X2NhcGFjaXR5KHRkaXNrLCB0dC0+Y2FwYWNpdHkodGFyZ2V0ZGF0YSkpOwotCWFkZF9k
aXNrKHRkaXNrKTsKLQogCXQtPnR5cGUgPSB0dDsKIAl0LT5kaXNrID0gdGRpc2s7CiAJdC0+ZGV2
ID0gZGV2OwogCisJc2V0X2NhcGFjaXR5KHRkaXNrLCB0dC0+Y2FwYWNpdHkodGFyZ2V0ZGF0YSkp
OworCWFkZF9kaXNrKHRkaXNrKTsKKworCWlmIChnZW5fcmVnaXN0ZXJfdGFyZ2V0KHQpKQorCQln
b3RvIGVycl9pbml0OworCisJaWYgKHR0LT5zeXNmc19pbml0KQorCQl0dC0+c3lzZnNfaW5pdCh0
KTsKKwogCW11dGV4X2xvY2soJmduLT5sb2NrKTsKIAlsaXN0X2FkZF90YWlsKCZ0LT5saXN0LCAm
Z24tPnRhcmdldHMpOwogCW11dGV4X3VubG9jaygmZ24tPmxvY2spOwpAQCAtMTEyLDIwICsxOTks
MTAgQEAgZXJyX3Q6CiAKIHN0YXRpYyB2b2lkIF9fZ2VuX3JlbW92ZV90YXJnZXQoc3RydWN0IG52
bV90YXJnZXQgKnQpCiB7Ci0Jc3RydWN0IG52bV90Z3RfdHlwZSAqdHQgPSB0LT50eXBlOwotCXN0
cnVjdCBnZW5kaXNrICp0ZGlzayA9IHQtPmRpc2s7Ci0Jc3RydWN0IHJlcXVlc3RfcXVldWUgKnEg
PSB0ZGlzay0+cXVldWU7Ci0KLQlkZWxfZ2VuZGlzayh0ZGlzayk7Ci0JYmxrX2NsZWFudXBfcXVl
dWUocSk7Ci0KLQlpZiAodHQtPmV4aXQpCi0JCXR0LT5leGl0KHRkaXNrLT5wcml2YXRlX2RhdGEp
OwotCi0JcHV0X2Rpc2sodGRpc2spOwotCiAJbGlzdF9kZWwoJnQtPmxpc3QpOwotCWtmcmVlKHQp
OworCWlmICh0LT50eXBlLT5zeXNmc19leGl0KQorCQl0LT50eXBlLT5zeXNmc19leGl0KHQpOwor
CWdlbl91bnJlZ2lzdGVyX3RhcmdldCh0KTsKIH0KIAogLyoqCkBAIC02MjcsNyArNzA0LDYgQEAg
c3RhdGljIHZvaWQgZ2VuX2x1bl9pbmZvX3ByaW50KHN0cnVjdCBudm1fZGV2ICpkZXYpCiAJc3Ry
dWN0IGdlbl9sdW4gKmx1bjsKIAl1bnNpZ25lZCBpbnQgaTsKIAotCiAJZ2VuX2Zvcl9lYWNoX2x1
bihnbiwgbHVuLCBpKSB7CiAJCXNwaW5fbG9jaygmbHVuLT52bHVuLmxvY2spOwogCmRpZmYgLS1n
aXQgYS9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmggYi9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgK
aW5kZXggZDE5MDc4Ni4uMzgyMzg5MSAxMDA2NDQKLS0tIGEvaW5jbHVkZS9saW51eC9saWdodG52
bS5oCisrKyBiL2luY2x1ZGUvbGludXgvbGlnaHRudm0uaApAQCAtMjExLDYgKzIxMSw4IEBAIHN0
cnVjdCBudm1fdGFyZ2V0IHsKIAlzdHJ1Y3QgbnZtX2RldiAqZGV2OwogCXN0cnVjdCBudm1fdGd0
X3R5cGUgKnR5cGU7CiAJc3RydWN0IGdlbmRpc2sgKmRpc2s7CisKKwlzdHJ1Y3Qga29iamVjdCBr
b2JqOwogfTsKIAogc3RydWN0IG52bV90Z3RfaW5zdGFuY2UgewpAQCAtNDM0LDYgKzQzNiwxMCBA
QCB0eXBlZGVmIGJsa19xY190IChudm1fdGd0X21ha2VfcnFfZm4pKHN0cnVjdCByZXF1ZXN0X3F1
ZXVlICosIHN0cnVjdCBiaW8gKik7CiB0eXBlZGVmIHNlY3Rvcl90IChudm1fdGd0X2NhcGFjaXR5
X2ZuKSh2b2lkICopOwogdHlwZWRlZiB2b2lkICoobnZtX3RndF9pbml0X2ZuKShzdHJ1Y3QgbnZt
X2RldiAqLCBzdHJ1Y3QgZ2VuZGlzayAqLCBpbnQsIGludCk7CiB0eXBlZGVmIHZvaWQgKG52bV90
Z3RfZXhpdF9mbikodm9pZCAqKTsKK3R5cGVkZWYgdm9pZCAobnZtX3RndF9zeXNmc19pbml0X2Zu
KShzdHJ1Y3QgbnZtX3RhcmdldCAqKTsKK3R5cGVkZWYgdm9pZCAobnZtX3RndF9zeXNmc19leGl0
X2ZuKShzdHJ1Y3QgbnZtX3RhcmdldCAqKTsKK3R5cGVkZWYgc3NpemVfdChudm1fdGd0X3N5c2Zz
X3Nob3dfZm4pKHN0cnVjdCBudm1fdGFyZ2V0ICosCisJCQkJICAgICBzdHJ1Y3QgYXR0cmlidXRl
ICosIGNoYXIgKik7CiAKIHN0cnVjdCBudm1fdGd0X3R5cGUgewogCWNvbnN0IGNoYXIgKm5hbWU7
CkBAIC00NDgsNiArNDU0LDEwIEBAIHN0cnVjdCBudm1fdGd0X3R5cGUgewogCW52bV90Z3RfaW5p
dF9mbiAqaW5pdDsKIAludm1fdGd0X2V4aXRfZm4gKmV4aXQ7CiAKKwludm1fdGd0X3N5c2ZzX2lu
aXRfZm4gKnN5c2ZzX2luaXQ7CisJbnZtX3RndF9zeXNmc19leGl0X2ZuICpzeXNmc19leGl0Owor
CW52bV90Z3Rfc3lzZnNfc2hvd19mbiAqc3lzZnNfc2hvdzsKKwogCS8qIEZvciBpbnRlcm5hbCB1
c2UgKi8KIAlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7CiB9OwotLSAKMi4xLjQKCgpfX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1udm1lIG1haWxpbmcg
bGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVh
ZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 6/6] lightnvm: expose gennvm target type through sysfs
@ 2016-06-29 14:51   ` Matias Bjørling
  0 siblings, 0 replies; 6+ messages in thread
From: Matias Bjørling @ 2016-06-29 14:51 UTC (permalink / raw)
  To: linux-block, linux-kernel, axboe, keith.busch, linux-nvme, dm-devel
  Cc: Simon A. F. Lund, Matias Bjørling

From: "Simon A. F. Lund" <slund@cnexlabs.com>

Create a sysfs directory for targets to expose their internal statistics
and knobs. The entries is exposed through the
/sys/block/<disk>/lightnvm/* directory.

It currently holds a single sysfs entry "type", which exports the target
type name.

Signed-off-by: Simon A. F. Lund <slund@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
---
 drivers/lightnvm/gennvm.c | 112 ++++++++++++++++++++++++++++++++++++++--------
 include/linux/lightnvm.h  |  10 +++++
 2 files changed, 104 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index b74174c..bfdad3c 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -20,6 +20,87 @@
 
 #include "gennvm.h"
 
+static struct attribute gen_type_attr = {
+	.name = "type",
+	.mode = S_IRUGO
+};
+
+static struct attribute *gen_target_attrs[] = {
+	&gen_type_attr,
+	NULL,
+};
+
+static ssize_t gen_target_attr_show(struct kobject *kobj,
+				struct attribute *attr,
+				char *page)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+
+	if (strcmp(attr->name, "type") == 0)
+		return scnprintf(page, PAGE_SIZE, "%s\n", t->type->name);
+
+	if (t->type->sysfs_show)
+		return t->type->sysfs_show(t, attr, page);
+
+	return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_target_attr_show`\n",
+			attr->name);
+}
+
+static const struct sysfs_ops target_sysfs_ops = {
+	.show = gen_target_attr_show,
+};
+
+static void gen_target_release(struct kobject *kobj)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+	struct nvm_tgt_type *tt = t->type;
+	struct gendisk *tdisk = t->disk;
+	struct request_queue *q = tdisk->queue;
+
+	pr_debug("gen: `gen_target_release`\n");
+
+	del_gendisk(tdisk);
+	blk_cleanup_queue(q);
+	put_disk(tdisk);
+
+	if (tt->exit)
+		tt->exit(tdisk->private_data);
+
+	kfree(t);
+}
+
+static struct kobj_type nvm_target_type = {
+	.sysfs_ops	= &target_sysfs_ops,
+	.default_attrs	= gen_target_attrs,
+	.release	= gen_target_release
+};
+
+void gen_unregister_target(struct nvm_target *t)
+{
+	kobject_uevent(&t->kobj, KOBJ_REMOVE);
+	kobject_del(&t->kobj);
+	kobject_put(&t->kobj);
+}
+
+int gen_register_target(struct nvm_target *t)
+{
+	struct gendisk *disk = t->disk;
+	struct device *dev = disk_to_dev(disk);
+	int ret;
+
+	ret = kobject_init_and_add(&t->kobj, &nvm_target_type,
+				   kobject_get(&dev->kobj), "%s", "lightnvm");
+	if (ret < 0) {
+		pr_err("gen: `_register_target` failed.\n");
+		kobject_put(&t->kobj);
+		return ret;
+	}
+
+	kobject_uevent(&t->kobj, KOBJ_ADD);
+	return 0;
+}
+
 static struct nvm_target *gen_find_target(struct gen_dev *gn, const char *name)
 {
 	struct nvm_target *tgt;
@@ -60,7 +141,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	}
 	mutex_unlock(&gn->lock);
 
-	t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
+	t = kzalloc(sizeof(struct nvm_target), GFP_KERNEL);
 	if (!t)
 		return -ENOMEM;
 
@@ -89,13 +170,19 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 
 	blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
 
-	set_capacity(tdisk, tt->capacity(targetdata));
-	add_disk(tdisk);
-
 	t->type = tt;
 	t->disk = tdisk;
 	t->dev = dev;
 
+	set_capacity(tdisk, tt->capacity(targetdata));
+	add_disk(tdisk);
+
+	if (gen_register_target(t))
+		goto err_init;
+
+	if (tt->sysfs_init)
+		tt->sysfs_init(t);
+
 	mutex_lock(&gn->lock);
 	list_add_tail(&t->list, &gn->targets);
 	mutex_unlock(&gn->lock);
@@ -112,20 +199,10 @@ err_t:
 
 static void __gen_remove_target(struct nvm_target *t)
 {
-	struct nvm_tgt_type *tt = t->type;
-	struct gendisk *tdisk = t->disk;
-	struct request_queue *q = tdisk->queue;
-
-	del_gendisk(tdisk);
-	blk_cleanup_queue(q);
-
-	if (tt->exit)
-		tt->exit(tdisk->private_data);
-
-	put_disk(tdisk);
-
 	list_del(&t->list);
-	kfree(t);
+	if (t->type->sysfs_exit)
+		t->type->sysfs_exit(t);
+	gen_unregister_target(t);
 }
 
 /**
@@ -627,7 +704,6 @@ static void gen_lun_info_print(struct nvm_dev *dev)
 	struct gen_lun *lun;
 	unsigned int i;
 
-
 	gen_for_each_lun(gn, lun, i) {
 		spin_lock(&lun->vlun.lock);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index d190786..3823891 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -211,6 +211,8 @@ struct nvm_target {
 	struct nvm_dev *dev;
 	struct nvm_tgt_type *type;
 	struct gendisk *disk;
+
+	struct kobject kobj;
 };
 
 struct nvm_tgt_instance {
@@ -434,6 +436,10 @@ 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_sysfs_init_fn)(struct nvm_target *);
+typedef void (nvm_tgt_sysfs_exit_fn)(struct nvm_target *);
+typedef ssize_t(nvm_tgt_sysfs_show_fn)(struct nvm_target *,
+				     struct attribute *, char *);
 
 struct nvm_tgt_type {
 	const char *name;
@@ -448,6 +454,10 @@ struct nvm_tgt_type {
 	nvm_tgt_init_fn *init;
 	nvm_tgt_exit_fn *exit;
 
+	nvm_tgt_sysfs_init_fn *sysfs_init;
+	nvm_tgt_sysfs_exit_fn *sysfs_exit;
+	nvm_tgt_sysfs_show_fn *sysfs_show;
+
 	/* For internal use */
 	struct list_head list;
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] lightnvm: expose gennvm target type through sysfs
@ 2016-06-29 14:51   ` Matias Bjørling
  0 siblings, 0 replies; 6+ messages in thread
From: Matias Bjørling @ 2016-06-29 14:51 UTC (permalink / raw)


From: "Simon A. F. Lund" <slund@cnexlabs.com>

Create a sysfs directory for targets to expose their internal statistics
and knobs. The entries is exposed through the
/sys/block/<disk>/lightnvm/* directory.

It currently holds a single sysfs entry "type", which exports the target
type name.

Signed-off-by: Simon A. F. Lund <slund at cnexlabs.com>
Signed-off-by: Matias Bj?rling <m at bjorling.me>
---
 drivers/lightnvm/gennvm.c | 112 ++++++++++++++++++++++++++++++++++++++--------
 include/linux/lightnvm.h  |  10 +++++
 2 files changed, 104 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index b74174c..bfdad3c 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -20,6 +20,87 @@
 
 #include "gennvm.h"
 
+static struct attribute gen_type_attr = {
+	.name = "type",
+	.mode = S_IRUGO
+};
+
+static struct attribute *gen_target_attrs[] = {
+	&gen_type_attr,
+	NULL,
+};
+
+static ssize_t gen_target_attr_show(struct kobject *kobj,
+				struct attribute *attr,
+				char *page)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+
+	if (strcmp(attr->name, "type") == 0)
+		return scnprintf(page, PAGE_SIZE, "%s\n", t->type->name);
+
+	if (t->type->sysfs_show)
+		return t->type->sysfs_show(t, attr, page);
+
+	return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_target_attr_show`\n",
+			attr->name);
+}
+
+static const struct sysfs_ops target_sysfs_ops = {
+	.show = gen_target_attr_show,
+};
+
+static void gen_target_release(struct kobject *kobj)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+	struct nvm_tgt_type *tt = t->type;
+	struct gendisk *tdisk = t->disk;
+	struct request_queue *q = tdisk->queue;
+
+	pr_debug("gen: `gen_target_release`\n");
+
+	del_gendisk(tdisk);
+	blk_cleanup_queue(q);
+	put_disk(tdisk);
+
+	if (tt->exit)
+		tt->exit(tdisk->private_data);
+
+	kfree(t);
+}
+
+static struct kobj_type nvm_target_type = {
+	.sysfs_ops	= &target_sysfs_ops,
+	.default_attrs	= gen_target_attrs,
+	.release	= gen_target_release
+};
+
+void gen_unregister_target(struct nvm_target *t)
+{
+	kobject_uevent(&t->kobj, KOBJ_REMOVE);
+	kobject_del(&t->kobj);
+	kobject_put(&t->kobj);
+}
+
+int gen_register_target(struct nvm_target *t)
+{
+	struct gendisk *disk = t->disk;
+	struct device *dev = disk_to_dev(disk);
+	int ret;
+
+	ret = kobject_init_and_add(&t->kobj, &nvm_target_type,
+				   kobject_get(&dev->kobj), "%s", "lightnvm");
+	if (ret < 0) {
+		pr_err("gen: `_register_target` failed.\n");
+		kobject_put(&t->kobj);
+		return ret;
+	}
+
+	kobject_uevent(&t->kobj, KOBJ_ADD);
+	return 0;
+}
+
 static struct nvm_target *gen_find_target(struct gen_dev *gn, const char *name)
 {
 	struct nvm_target *tgt;
@@ -60,7 +141,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	}
 	mutex_unlock(&gn->lock);
 
-	t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
+	t = kzalloc(sizeof(struct nvm_target), GFP_KERNEL);
 	if (!t)
 		return -ENOMEM;
 
@@ -89,13 +170,19 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 
 	blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
 
-	set_capacity(tdisk, tt->capacity(targetdata));
-	add_disk(tdisk);
-
 	t->type = tt;
 	t->disk = tdisk;
 	t->dev = dev;
 
+	set_capacity(tdisk, tt->capacity(targetdata));
+	add_disk(tdisk);
+
+	if (gen_register_target(t))
+		goto err_init;
+
+	if (tt->sysfs_init)
+		tt->sysfs_init(t);
+
 	mutex_lock(&gn->lock);
 	list_add_tail(&t->list, &gn->targets);
 	mutex_unlock(&gn->lock);
@@ -112,20 +199,10 @@ err_t:
 
 static void __gen_remove_target(struct nvm_target *t)
 {
-	struct nvm_tgt_type *tt = t->type;
-	struct gendisk *tdisk = t->disk;
-	struct request_queue *q = tdisk->queue;
-
-	del_gendisk(tdisk);
-	blk_cleanup_queue(q);
-
-	if (tt->exit)
-		tt->exit(tdisk->private_data);
-
-	put_disk(tdisk);
-
 	list_del(&t->list);
-	kfree(t);
+	if (t->type->sysfs_exit)
+		t->type->sysfs_exit(t);
+	gen_unregister_target(t);
 }
 
 /**
@@ -627,7 +704,6 @@ static void gen_lun_info_print(struct nvm_dev *dev)
 	struct gen_lun *lun;
 	unsigned int i;
 
-
 	gen_for_each_lun(gn, lun, i) {
 		spin_lock(&lun->vlun.lock);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index d190786..3823891 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -211,6 +211,8 @@ struct nvm_target {
 	struct nvm_dev *dev;
 	struct nvm_tgt_type *type;
 	struct gendisk *disk;
+
+	struct kobject kobj;
 };
 
 struct nvm_tgt_instance {
@@ -434,6 +436,10 @@ 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_sysfs_init_fn)(struct nvm_target *);
+typedef void (nvm_tgt_sysfs_exit_fn)(struct nvm_target *);
+typedef ssize_t(nvm_tgt_sysfs_show_fn)(struct nvm_target *,
+				     struct attribute *, char *);
 
 struct nvm_tgt_type {
 	const char *name;
@@ -448,6 +454,10 @@ struct nvm_tgt_type {
 	nvm_tgt_init_fn *init;
 	nvm_tgt_exit_fn *exit;
 
+	nvm_tgt_sysfs_init_fn *sysfs_init;
+	nvm_tgt_sysfs_exit_fn *sysfs_exit;
+	nvm_tgt_sysfs_show_fn *sysfs_show;
+
 	/* For internal use */
 	struct list_head list;
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] lightnvm: expose gennvm target type through sysfs
@ 2016-06-29 14:51   ` Matias Bjørling
  0 siblings, 0 replies; 6+ messages in thread
From: Matias Bjørling @ 2016-06-29 14:51 UTC (permalink / raw)
  To: linux-block, linux-kernel, axboe, keith.busch, linux-nvme, dm-devel
  Cc: Simon A. F. Lund, Matias Bjørling

From: "Simon A. F. Lund" <slund@cnexlabs.com>

Create a sysfs directory for targets to expose their internal statistics
and knobs. The entries is exposed through the
/sys/block/<disk>/lightnvm/* directory.

It currently holds a single sysfs entry "type", which exports the target
type name.

Signed-off-by: Simon A. F. Lund <slund@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
---
 drivers/lightnvm/gennvm.c | 112 ++++++++++++++++++++++++++++++++++++++--------
 include/linux/lightnvm.h  |  10 +++++
 2 files changed, 104 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index b74174c..bfdad3c 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -20,6 +20,87 @@
 
 #include "gennvm.h"
 
+static struct attribute gen_type_attr = {
+	.name = "type",
+	.mode = S_IRUGO
+};
+
+static struct attribute *gen_target_attrs[] = {
+	&gen_type_attr,
+	NULL,
+};
+
+static ssize_t gen_target_attr_show(struct kobject *kobj,
+				struct attribute *attr,
+				char *page)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+
+	if (strcmp(attr->name, "type") == 0)
+		return scnprintf(page, PAGE_SIZE, "%s\n", t->type->name);
+
+	if (t->type->sysfs_show)
+		return t->type->sysfs_show(t, attr, page);
+
+	return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_target_attr_show`\n",
+			attr->name);
+}
+
+static const struct sysfs_ops target_sysfs_ops = {
+	.show = gen_target_attr_show,
+};
+
+static void gen_target_release(struct kobject *kobj)
+{
+	struct nvm_target *t = container_of(kobj, struct nvm_target, kobj);
+	struct nvm_tgt_type *tt = t->type;
+	struct gendisk *tdisk = t->disk;
+	struct request_queue *q = tdisk->queue;
+
+	pr_debug("gen: `gen_target_release`\n");
+
+	del_gendisk(tdisk);
+	blk_cleanup_queue(q);
+	put_disk(tdisk);
+
+	if (tt->exit)
+		tt->exit(tdisk->private_data);
+
+	kfree(t);
+}
+
+static struct kobj_type nvm_target_type = {
+	.sysfs_ops	= &target_sysfs_ops,
+	.default_attrs	= gen_target_attrs,
+	.release	= gen_target_release
+};
+
+void gen_unregister_target(struct nvm_target *t)
+{
+	kobject_uevent(&t->kobj, KOBJ_REMOVE);
+	kobject_del(&t->kobj);
+	kobject_put(&t->kobj);
+}
+
+int gen_register_target(struct nvm_target *t)
+{
+	struct gendisk *disk = t->disk;
+	struct device *dev = disk_to_dev(disk);
+	int ret;
+
+	ret = kobject_init_and_add(&t->kobj, &nvm_target_type,
+				   kobject_get(&dev->kobj), "%s", "lightnvm");
+	if (ret < 0) {
+		pr_err("gen: `_register_target` failed.\n");
+		kobject_put(&t->kobj);
+		return ret;
+	}
+
+	kobject_uevent(&t->kobj, KOBJ_ADD);
+	return 0;
+}
+
 static struct nvm_target *gen_find_target(struct gen_dev *gn, const char *name)
 {
 	struct nvm_target *tgt;
@@ -60,7 +141,7 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	}
 	mutex_unlock(&gn->lock);
 
-	t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
+	t = kzalloc(sizeof(struct nvm_target), GFP_KERNEL);
 	if (!t)
 		return -ENOMEM;
 
@@ -89,13 +170,19 @@ static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 
 	blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
 
-	set_capacity(tdisk, tt->capacity(targetdata));
-	add_disk(tdisk);
-
 	t->type = tt;
 	t->disk = tdisk;
 	t->dev = dev;
 
+	set_capacity(tdisk, tt->capacity(targetdata));
+	add_disk(tdisk);
+
+	if (gen_register_target(t))
+		goto err_init;
+
+	if (tt->sysfs_init)
+		tt->sysfs_init(t);
+
 	mutex_lock(&gn->lock);
 	list_add_tail(&t->list, &gn->targets);
 	mutex_unlock(&gn->lock);
@@ -112,20 +199,10 @@ err_t:
 
 static void __gen_remove_target(struct nvm_target *t)
 {
-	struct nvm_tgt_type *tt = t->type;
-	struct gendisk *tdisk = t->disk;
-	struct request_queue *q = tdisk->queue;
-
-	del_gendisk(tdisk);
-	blk_cleanup_queue(q);
-
-	if (tt->exit)
-		tt->exit(tdisk->private_data);
-
-	put_disk(tdisk);
-
 	list_del(&t->list);
-	kfree(t);
+	if (t->type->sysfs_exit)
+		t->type->sysfs_exit(t);
+	gen_unregister_target(t);
 }
 
 /**
@@ -627,7 +704,6 @@ static void gen_lun_info_print(struct nvm_dev *dev)
 	struct gen_lun *lun;
 	unsigned int i;
 
-
 	gen_for_each_lun(gn, lun, i) {
 		spin_lock(&lun->vlun.lock);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index d190786..3823891 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -211,6 +211,8 @@ struct nvm_target {
 	struct nvm_dev *dev;
 	struct nvm_tgt_type *type;
 	struct gendisk *disk;
+
+	struct kobject kobj;
 };
 
 struct nvm_tgt_instance {
@@ -434,6 +436,10 @@ 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_sysfs_init_fn)(struct nvm_target *);
+typedef void (nvm_tgt_sysfs_exit_fn)(struct nvm_target *);
+typedef ssize_t(nvm_tgt_sysfs_show_fn)(struct nvm_target *,
+				     struct attribute *, char *);
 
 struct nvm_tgt_type {
 	const char *name;
@@ -448,6 +454,10 @@ struct nvm_tgt_type {
 	nvm_tgt_init_fn *init;
 	nvm_tgt_exit_fn *exit;
 
+	nvm_tgt_sysfs_init_fn *sysfs_init;
+	nvm_tgt_sysfs_exit_fn *sysfs_exit;
+	nvm_tgt_sysfs_show_fn *sysfs_show;
+
 	/* For internal use */
 	struct list_head list;
 };
-- 
2.1.4

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-06-29 14:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-10 12:22 [PATCH 6/6] lightnvm: expose gennvm target type through sysfs Matias Bjørling
2016-06-10 12:22 ` Matias Bjørling
2016-06-29 14:51 [PATCH 0/6] enable sysfs for lightnvm Matias Bjørling
2016-06-29 14:51 ` [PATCH 6/6] lightnvm: expose gennvm target type through sysfs Matias Bjørling
2016-06-29 14:51   ` Matias Bjørling
2016-06-29 14:51   ` Matias Bjørling
2016-06-29 14:51   ` Matias Bjørling

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.