[PATCH 09/10] Sysfs entries for multipath head
Anish M Jhaveri
anish.jhaveri at paviliondata.com
Mon Sep 11 21:32:05 PDT 2017
Sysfs entries for active path and ioctl redirecting to active namespace when device handle is head namespace.
Signed-off-by: Anish M Jhaveri <anish.jhaveri at paviliondata.com>
---
drivers/nvme/host/core.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 95 insertions(+), 3 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 4043c00..82f8e10 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1600,6 +1600,18 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct nvme_ns *ns = bdev->bd_disk->private_data;
+ struct nvme_ns *mpath_ns = ns;
+
+ ns = nvme_get_active_ns_for_mpath_ns(mpath_ns);
+ if (!ns) {
+ /* fail IOCTL if no active ns found for mpath */
+ return -ENOTTY;
+ }
+
+ if (test_bit(NVME_NS_REMOVING, &ns->flags) || (ns->ctrl->state != NVME_CTRL_LIVE)) {
+ return -ENOTTY;
+ }
+
switch (cmd) {
case NVME_IOCTL_ID:
@@ -1642,7 +1654,8 @@ static void nvme_release(struct gendisk *disk, fmode_t mode)
{
struct nvme_ns *ns = disk->private_data;
- module_put(ns->ctrl->ops->module);
+ if (!test_bit(NVME_NS_ROOT, &ns->flags))
+ module_put(ns->ctrl->ops->module);
nvme_put_ns(ns);
}
@@ -1747,6 +1760,8 @@ static void nvme_config_discard(struct nvme_ns *ns)
static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
{
+ int res = 0;
+ char *buf;
if (nvme_identify_ns(ns->ctrl, ns->ns_id, id)) {
dev_warn(ns->ctrl->dev, "%s: Identify failure\n", __func__);
return -ENODEV;
@@ -1770,6 +1785,17 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
"%s: Identify Descriptors failed\n", __func__);
}
+ /*Retrieve NGUID or UUID from target device as it needs to be persistent across boot.*/
+ if (!test_bit(NVME_NS_ROOT, &ns->flags)) {
+ res = nvme_get_mpath_nguid(ns->ctrl, ns->ns_id, &buf);
+ if (res) {
+ dev_warn(ns->ctrl->dev, "%s: Failed to get NGUID\n", __func__);
+ } else {
+ memcpy(ns->mpath_nguid, buf, NVME_NIDT_NGUID_LEN);
+ kfree(buf);
+ }
+ }
+
return 0;
}
@@ -1779,6 +1805,9 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
struct nvme_ctrl *ctrl = ns->ctrl;
u16 bs;
+ /*For device to shared, Bit 0 is set nmic.
+ We use this to make device part of multipath group.*/
+ ns->nmic = id->nmic;
/*
* If identify namespace failed, use default 512 byte block size so
* block layer can use before failing read/write for 0 capacity.
@@ -1810,15 +1839,19 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
static int nvme_revalidate_disk(struct gendisk *disk)
{
+ struct nvme_ns *mpath_ns;
struct nvme_ns *ns = disk->private_data;
struct nvme_id_ns *id = NULL;
int ret;
+ mpath_ns = ns;
if (test_bit(NVME_NS_DEAD, &ns->flags)) {
set_capacity(disk, 0);
return -ENODEV;
}
+ ns = nvme_get_ns_for_mpath_ns(mpath_ns);
+
ret = nvme_revalidate_ns(ns, &id);
if (ret)
return ret;
@@ -2641,6 +2674,37 @@ static ssize_t eui_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(eui, S_IRUGO, eui_show, NULL);
+static ssize_t active_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
+ int ret = 0;
+ if (!test_bit(NVME_NS_ROOT, &ns->flags)) {
+ ret = sprintf(buf, "%d\n", ns->active);
+ }
+ return ret;
+}
+static DEVICE_ATTR(active, S_IRUGO, active_show, NULL);
+
+static ssize_t active_path_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct nvme_ns *mpath_ns = nvme_get_ns_from_dev(dev);
+ struct nvme_ns *nsa;
+ int ret = 0;
+ if (test_bit(NVME_NS_ROOT, &mpath_ns->flags)) {
+ mutex_lock(&mpath_ns->ctrl->namespaces_mutex);
+ list_for_each_entry(nsa, &mpath_ns->ctrl->namespaces, mpathlist) {
+ if (nsa->active) {
+ ret = sprintf(buf, "nvme%dn%d\n", nsa->ctrl->instance, nsa->instance);
+ break;
+ }
+ }
+ mutex_unlock(&mpath_ns->ctrl->namespaces_mutex);
+ }
+ return ret;
+}
+static DEVICE_ATTR(active_path, S_IRUGO, active_path_show, NULL);
+
static ssize_t nsid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -2649,12 +2713,23 @@ static ssize_t nsid_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(nsid, S_IRUGO, nsid_show, NULL);
+static ssize_t mpath_nguid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
+ return sprintf(buf, "%pU\n", ns->mpath_nguid);
+}
+static DEVICE_ATTR(mpath_nguid, S_IRUGO, mpath_nguid_show, NULL);
+
static struct attribute *nvme_ns_attrs[] = {
&dev_attr_wwid.attr,
&dev_attr_uuid.attr,
&dev_attr_nguid.attr,
&dev_attr_eui.attr,
&dev_attr_nsid.attr,
+ &dev_attr_active.attr,
+ &dev_attr_active_path.attr,
+ &dev_attr_mpath_nguid.attr,
NULL,
};
@@ -2714,6 +2789,9 @@ static ssize_t nvme_sysfs_delete(struct device *dev,
{
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ if (test_bit(NVME_CTRL_MULTIPATH, &ctrl->flags))
+ return 0;
+
if (device_remove_file_self(dev, attr))
ctrl->ops->delete_ctrl(ctrl);
return count;
@@ -2758,8 +2836,22 @@ static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev,
char *buf)
{
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
-
- return snprintf(buf, PAGE_SIZE, "%s\n", ctrl->subnqn);
+ struct nvme_ns *nsa = NULL;
+ ssize_t ret = 0;
+ if (test_bit(NVME_CTRL_MULTIPATH, &ctrl->flags)) {
+ /* mpath ctrl, iterate and send it to nsa->ctrl */
+ mutex_lock(&ctrl->namespaces_mutex);
+ list_for_each_entry(nsa, &ctrl->namespaces, mpathlist) {
+ if (nsa->ctrl && nsa->ctrl->ops) {
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", nsa->ctrl->subnqn);
+ break;
+ }
+ }
+ mutex_unlock(&ctrl->namespaces_mutex);
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", ctrl->subnqn);
+ }
+ return ret;
}
static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL);
--
2.9.3
More information about the Linux-nvme
mailing list