Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33b14f67 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Jens Axboe
Browse files

nvme: register ns_id attributes as default sysfs groups



We should be registering the ns_id attribute as default sysfs
attribute groups, otherwise we have a race condition between
the uevent and the attributes appearing in sysfs.

Suggested-by: default avatarBart van Assche <bvanassche@acm.org>
Reviewed-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent fef912bf
Loading
Loading
Loading
Loading
+9 −12
Original line number Diff line number Diff line
@@ -2734,6 +2734,14 @@ const struct attribute_group nvme_ns_id_attr_group = {
	.is_visible	= nvme_ns_id_attrs_are_visible,
};

const struct attribute_group *nvme_ns_id_attr_groups[] = {
	&nvme_ns_id_attr_group,
#ifdef CONFIG_NVM
	&nvme_nvm_attr_group,
#endif
	NULL,
};

#define nvme_show_str_function(field)						\
static ssize_t  field##_show(struct device *dev,				\
			    struct device_attribute *attr, char *buf)		\
@@ -3099,14 +3107,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)

	nvme_get_ctrl(ctrl);

	device_add_disk(ctrl->device, ns->disk, NULL);
	if (sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
					&nvme_ns_id_attr_group))
		pr_warn("%s: failed to create sysfs group for identification\n",
			ns->disk->disk_name);
	if (ns->ndev && nvme_nvm_register_sysfs(ns))
		pr_warn("%s: failed to register lightnvm sysfs group for identification\n",
			ns->disk->disk_name);
	device_add_disk(ctrl->device, ns->disk, nvme_ns_id_attr_groups);

	nvme_mpath_add_disk(ns, id);
	nvme_fault_inject_init(ns);
@@ -3132,10 +3133,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)

	nvme_fault_inject_fini(ns);
	if (ns->disk && ns->disk->flags & GENHD_FL_UP) {
		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
					&nvme_ns_id_attr_group);
		if (ns->ndev)
			nvme_nvm_unregister_sysfs(ns);
		del_gendisk(ns->disk);
		blk_cleanup_queue(ns->queue);
		if (blk_get_integrity(ns->disk))
+44 −61
Original line number Diff line number Diff line
@@ -1190,10 +1190,29 @@ static NVM_DEV_ATTR_12_RO(multiplane_modes);
static NVM_DEV_ATTR_12_RO(media_capabilities);
static NVM_DEV_ATTR_12_RO(max_phys_secs);

static struct attribute *nvm_dev_attrs_12[] = {
/* 2.0 values */
static NVM_DEV_ATTR_20_RO(groups);
static NVM_DEV_ATTR_20_RO(punits);
static NVM_DEV_ATTR_20_RO(chunks);
static NVM_DEV_ATTR_20_RO(clba);
static NVM_DEV_ATTR_20_RO(ws_min);
static NVM_DEV_ATTR_20_RO(ws_opt);
static NVM_DEV_ATTR_20_RO(maxoc);
static NVM_DEV_ATTR_20_RO(maxocpu);
static NVM_DEV_ATTR_20_RO(mw_cunits);
static NVM_DEV_ATTR_20_RO(write_typ);
static NVM_DEV_ATTR_20_RO(write_max);
static NVM_DEV_ATTR_20_RO(reset_typ);
static NVM_DEV_ATTR_20_RO(reset_max);

static struct attribute *nvm_dev_attrs[] = {
	/* version agnostic attrs */
	&dev_attr_version.attr,
	&dev_attr_capabilities.attr,
	&dev_attr_read_typ.attr,
	&dev_attr_read_max.attr,

	/* 1.2 attrs */
	&dev_attr_vendor_opcode.attr,
	&dev_attr_device_mode.attr,
	&dev_attr_media_manager.attr,
@@ -1208,8 +1227,6 @@ static struct attribute *nvm_dev_attrs_12[] = {
	&dev_attr_page_size.attr,
	&dev_attr_hw_sector_size.attr,
	&dev_attr_oob_sector_size.attr,
	&dev_attr_read_typ.attr,
	&dev_attr_read_max.attr,
	&dev_attr_prog_typ.attr,
	&dev_attr_prog_max.attr,
	&dev_attr_erase_typ.attr,
@@ -1218,33 +1235,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
	&dev_attr_media_capabilities.attr,
	&dev_attr_max_phys_secs.attr,

	NULL,
};

static const struct attribute_group nvm_dev_attr_group_12 = {
	.name		= "lightnvm",
	.attrs		= nvm_dev_attrs_12,
};

/* 2.0 values */
static NVM_DEV_ATTR_20_RO(groups);
static NVM_DEV_ATTR_20_RO(punits);
static NVM_DEV_ATTR_20_RO(chunks);
static NVM_DEV_ATTR_20_RO(clba);
static NVM_DEV_ATTR_20_RO(ws_min);
static NVM_DEV_ATTR_20_RO(ws_opt);
static NVM_DEV_ATTR_20_RO(maxoc);
static NVM_DEV_ATTR_20_RO(maxocpu);
static NVM_DEV_ATTR_20_RO(mw_cunits);
static NVM_DEV_ATTR_20_RO(write_typ);
static NVM_DEV_ATTR_20_RO(write_max);
static NVM_DEV_ATTR_20_RO(reset_typ);
static NVM_DEV_ATTR_20_RO(reset_max);

static struct attribute *nvm_dev_attrs_20[] = {
	&dev_attr_version.attr,
	&dev_attr_capabilities.attr,

	/* 2.0 attrs */
	&dev_attr_groups.attr,
	&dev_attr_punits.attr,
	&dev_attr_chunks.attr,
@@ -1255,8 +1246,6 @@ static struct attribute *nvm_dev_attrs_20[] = {
	&dev_attr_maxocpu.attr,
	&dev_attr_mw_cunits.attr,

	&dev_attr_read_typ.attr,
	&dev_attr_read_max.attr,
	&dev_attr_write_typ.attr,
	&dev_attr_write_max.attr,
	&dev_attr_reset_typ.attr,
@@ -1265,44 +1254,38 @@ static struct attribute *nvm_dev_attrs_20[] = {
	NULL,
};

static const struct attribute_group nvm_dev_attr_group_20 = {
	.name		= "lightnvm",
	.attrs		= nvm_dev_attrs_20,
};

int nvme_nvm_register_sysfs(struct nvme_ns *ns)
static umode_t nvm_dev_attrs_visible(struct kobject *kobj,
				     struct attribute *attr, int index)
{
	struct device *dev = container_of(kobj, struct device, kobj);
	struct gendisk *disk = dev_to_disk(dev);
	struct nvme_ns *ns = disk->private_data;
	struct nvm_dev *ndev = ns->ndev;
	struct nvm_geo *geo = &ndev->geo;
	struct device_attribute *dev_attr =
		container_of(attr, typeof(*dev_attr), attr);

	if (!ndev)
		return -EINVAL;

	switch (geo->major_ver_id) {
	case 1:
		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
					&nvm_dev_attr_group_12);
	case 2:
		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
					&nvm_dev_attr_group_20);
	}

	return -EINVAL;
}
		return 0;

void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
{
	struct nvm_dev *ndev = ns->ndev;
	struct nvm_geo *geo = &ndev->geo;
	if (dev_attr->show == nvm_dev_attr_show)
		return attr->mode;

	switch (geo->major_ver_id) {
	switch (ndev->geo.major_ver_id) {
	case 1:
		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
					&nvm_dev_attr_group_12);
		if (dev_attr->show == nvm_dev_attr_show_12)
			return attr->mode;
		break;
	case 2:
		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
					&nvm_dev_attr_group_20);
		if (dev_attr->show == nvm_dev_attr_show_20)
			return attr->mode;
		break;
	}

	return 0;
}

const struct attribute_group nvme_nvm_attr_group = {
	.name		= "lightnvm",
	.attrs		= nvm_dev_attrs,
	.is_visible	= nvm_dev_attrs_visible,
};
+4 −11
Original line number Diff line number Diff line
@@ -282,13 +282,9 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
	if (!head->disk)
		return;

	if (!(head->disk->flags & GENHD_FL_UP)) {
		device_add_disk(&head->subsys->dev, head->disk, NULL);
		if (sysfs_create_group(&disk_to_dev(head->disk)->kobj,
				&nvme_ns_id_attr_group))
			dev_warn(&head->subsys->dev,
				 "failed to create id group.\n");
	}
	if (!(head->disk->flags & GENHD_FL_UP))
		device_add_disk(&head->subsys->dev, head->disk,
				nvme_ns_id_attr_groups);

	kblockd_schedule_work(&ns->head->requeue_work);
}
@@ -494,11 +490,8 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
{
	if (!head->disk)
		return;
	if (head->disk->flags & GENHD_FL_UP) {
		sysfs_remove_group(&disk_to_dev(head->disk)->kobj,
				   &nvme_ns_id_attr_group);
	if (head->disk->flags & GENHD_FL_UP)
		del_gendisk(head->disk);
	}
	blk_set_queue_dying(head->disk->queue);
	/* make sure all pending bios are cleaned up */
	kblockd_schedule_work(&head->requeue_work);
+2 −8
Original line number Diff line number Diff line
@@ -459,7 +459,7 @@ int nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl);
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,
		void *log, size_t size, u64 offset);

extern const struct attribute_group nvme_ns_id_attr_group;
extern const struct attribute_group *nvme_ns_id_attr_groups[];
extern const struct block_device_operations nvme_ns_head_ops;

#ifdef CONFIG_NVME_MULTIPATH
@@ -551,8 +551,7 @@ static inline void nvme_mpath_stop(struct nvme_ctrl *ctrl)
void nvme_nvm_update_nvm_info(struct nvme_ns *ns);
int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node);
void nvme_nvm_unregister(struct nvme_ns *ns);
int nvme_nvm_register_sysfs(struct nvme_ns *ns);
void nvme_nvm_unregister_sysfs(struct nvme_ns *ns);
extern const struct attribute_group nvme_nvm_attr_group;
int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg);
#else
static inline void nvme_nvm_update_nvm_info(struct nvme_ns *ns) {};
@@ -563,11 +562,6 @@ static inline int nvme_nvm_register(struct nvme_ns *ns, char *disk_name,
}

static inline void nvme_nvm_unregister(struct nvme_ns *ns) {};
static inline int nvme_nvm_register_sysfs(struct nvme_ns *ns)
{
	return 0;
}
static inline void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) {};
static inline int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd,
							unsigned long arg)
{