* [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.