struct bio *bio;
nvme_mpath_clear_current_path(ns);
+ atomic_long_inc(&ns->failover);
/*
* If we got back an ANA error, we know the controller is alive but not
DEVICE_ATTR_RW(delayed_removal_secs);
+static ssize_t multipath_failover_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
+
+ return sysfs_emit(buf, "%lu\n", atomic_long_read(&ns->failover));
+}
+
+static ssize_t multipath_failover_count_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long failover;
+ int ret;
+ struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
+
+ ret = kstrtoul(buf, 0, &failover);
+ if (ret)
+ return -EINVAL;
+
+ atomic_long_set(&ns->failover, failover);
+
+ return count;
+}
+
+DEVICE_ATTR_RW(multipath_failover_count);
+
static int nvme_lookup_ana_group_desc(struct nvme_ctrl *ctrl,
struct nvme_ana_group_desc *desc, void *data)
{
#ifdef CONFIG_NVME_MULTIPATH
enum nvme_ana_state ana_state;
u32 ana_grpid;
+ atomic_long_t failover;
#endif
atomic_long_t retries;
struct list_head siblings;
extern struct device_attribute dev_attr_queue_depth;
extern struct device_attribute dev_attr_numa_nodes;
extern struct device_attribute dev_attr_delayed_removal_secs;
+extern struct device_attribute dev_attr_multipath_failover_count;
extern struct device_attribute subsys_attr_iopolicy;
static inline bool nvme_disk_is_ns_head(struct gendisk *disk)
static struct attribute *nvme_ns_diag_attrs[] = {
&dev_attr_command_retries_count.attr,
+#ifdef CONFIG_NVME_MULTIPATH
+ &dev_attr_multipath_failover_count.attr,
+#endif
NULL,
};
if (nvme_disk_is_ns_head(dev_to_disk(dev)))
return 0;
}
-
+#ifdef CONFIG_NVME_MULTIPATH
+ if (a == &dev_attr_multipath_failover_count.attr) {
+ if (nvme_disk_is_ns_head(dev_to_disk(dev)))
+ return 0;
+ }
+#endif
return a->mode;
}