public inbox for linux-block@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2] ublk: persistent device links
@ 2026-02-20 15:06 Hannes Reinecke
  2026-02-20 16:16 ` Ming Lei
  0 siblings, 1 reply; 2+ messages in thread
From: Hannes Reinecke @ 2026-02-20 15:06 UTC (permalink / raw)
  To: Ming Lei; +Cc: linux-block, Jens Axboe, Hannes Reinecke

Implement a 'uuid' parameter to export a device UUID in a sysfs
attribute 'uuid'. The ublk server is required to set the uuid
parameter when creating the device.
This allows udev to create persistent device links for ublk devices
eg with this rule:

KERNEL=="ublk*", ATTRS{uuid}=="?*", SYMLINK+="disk/by-id/ublk-$attr{uuid}"

Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
 drivers/block/ublk_drv.c      | 55 +++++++++++++++++++++++++++++++++--
 include/uapi/linux/ublk_cmd.h |  6 ++++
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index aaf94d2fb789..ffbd5acda36b 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -89,7 +89,7 @@
 	(UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \
 	 UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED |    \
 	 UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT | \
-	 UBLK_PARAM_TYPE_INTEGRITY)
+	 UBLK_PARAM_TYPE_INTEGRITY | UBLK_PARAM_TYPE_UUID)
 
 struct ublk_uring_cmd_pdu {
 	/*
@@ -761,6 +761,14 @@ static int ublk_validate_params(const struct ublk_device *ub)
 			return -EINVAL;
 	}
 
+	if (ub->params.types & UBLK_PARAM_TYPE_UUID) {
+		const struct ublk_param_uuid *p = &ub->params.uuid;
+		uuid_t uuid;
+
+		import_uuid(&uuid, p->uuid);
+		if (uuid_is_null(&uuid))
+			return -EINVAL;
+	}
 	return 0;
 }
 
@@ -2971,6 +2979,49 @@ static int ublk_add_chdev(struct ublk_device *ub)
 	return ret;
 }
 
+static ssize_t uuid_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+	struct ublk_device *ub = disk->private_data;
+	const struct ublk_param_uuid *p = &ub->params.uuid;
+	uuid_t uuid;
+
+	import_uuid(&uuid, p->uuid);
+	return sprintf(buf, "%pU\n", &uuid);
+}
+
+static DEVICE_ATTR_RO(uuid);
+
+static struct attribute *ublk_attrs[] = {
+	&dev_attr_uuid.attr,
+	NULL,
+};
+
+static umode_t ublk_attrs_are_visible(struct kobject *kobj,
+		struct attribute *a, int n)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct gendisk *disk = dev_to_disk(dev);
+	struct ublk_device *ub = disk->private_data;
+
+	if (a == &dev_attr_uuid.attr &&
+	    (ub->params.types & UBLK_PARAM_TYPE_UUID))
+		return S_IRUGO;
+
+	return a->mode;
+}
+
+static const struct attribute_group ublk_attr_group = {
+	.attrs = ublk_attrs,
+	.is_visible = ublk_attrs_are_visible,
+};
+
+static const struct attribute_group *ublk_attr_groups[] = {
+	&ublk_attr_group,
+	NULL,
+};
+
 /* align max io buffer size with PAGE_SIZE */
 static void ublk_align_max_io_size(struct ublk_device *ub)
 {
@@ -3149,7 +3200,7 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
 			goto out_put_cdev;
 	}
 
-	ret = add_disk(disk);
+	ret = device_add_disk(NULL, disk, ublk_attr_groups);
 	if (ret)
 		goto out_put_cdev;
 
diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
index 90f47da4f435..b30a0de44b85 100644
--- a/include/uapi/linux/ublk_cmd.h
+++ b/include/uapi/linux/ublk_cmd.h
@@ -630,6 +630,10 @@ struct ublk_param_integrity {
 	__u8	pad[5];
 };
 
+struct ublk_param_uuid {
+	__u8	uuid[16];
+};
+
 struct ublk_params {
 	/*
 	 * Total length of parameters, userspace has to set 'len' for both
@@ -645,6 +649,7 @@ struct ublk_params {
 #define UBLK_PARAM_TYPE_DMA_ALIGN       (1 << 4)
 #define UBLK_PARAM_TYPE_SEGMENT         (1 << 5)
 #define UBLK_PARAM_TYPE_INTEGRITY       (1 << 6) /* requires UBLK_F_INTEGRITY */
+#define UBLK_PARAM_TYPE_UUID            (1 << 7)
 	__u32	types;			/* types of parameter included */
 
 	struct ublk_param_basic		basic;
@@ -654,6 +659,7 @@ struct ublk_params {
 	struct ublk_param_dma_align	dma;
 	struct ublk_param_segment	seg;
 	struct ublk_param_integrity	integrity;
+	struct ublk_param_uuid		uuid;
 };
 
 #endif
-- 
2.43.0


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

* Re: [PATCHv2] ublk: persistent device links
  2026-02-20 15:06 [PATCHv2] ublk: persistent device links Hannes Reinecke
@ 2026-02-20 16:16 ` Ming Lei
  0 siblings, 0 replies; 2+ messages in thread
From: Ming Lei @ 2026-02-20 16:16 UTC (permalink / raw)
  To: Hannes Reinecke; +Cc: linux-block, Jens Axboe

On Fri, Feb 20, 2026 at 04:06:51PM +0100, Hannes Reinecke wrote:
> Implement a 'uuid' parameter to export a device UUID in a sysfs
> attribute 'uuid'. The ublk server is required to set the uuid
> parameter when creating the device.
> This allows udev to create persistent device links for ublk devices
> eg with this rule:
> 
> KERNEL=="ublk*", ATTRS{uuid}=="?*", SYMLINK+="disk/by-id/ublk-$attr{uuid}"
> 
> Signed-off-by: Hannes Reinecke <hare@kernel.org>
> ---
>  drivers/block/ublk_drv.c      | 55 +++++++++++++++++++++++++++++++++--
>  include/uapi/linux/ublk_cmd.h |  6 ++++
>  2 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index aaf94d2fb789..ffbd5acda36b 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -89,7 +89,7 @@
>  	(UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \
>  	 UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED |    \
>  	 UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT | \
> -	 UBLK_PARAM_TYPE_INTEGRITY)
> +	 UBLK_PARAM_TYPE_INTEGRITY | UBLK_PARAM_TYPE_UUID)
>  
>  struct ublk_uring_cmd_pdu {
>  	/*
> @@ -761,6 +761,14 @@ static int ublk_validate_params(const struct ublk_device *ub)
>  			return -EINVAL;
>  	}
>  
> +	if (ub->params.types & UBLK_PARAM_TYPE_UUID) {
> +		const struct ublk_param_uuid *p = &ub->params.uuid;
> +		uuid_t uuid;
> +
> +		import_uuid(&uuid, p->uuid);
> +		if (uuid_is_null(&uuid))
> +			return -EINVAL;
> +	}
>  	return 0;
>  }
>  
> @@ -2971,6 +2979,49 @@ static int ublk_add_chdev(struct ublk_device *ub)
>  	return ret;
>  }
>  
> +static ssize_t uuid_show(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct gendisk *disk = dev_to_disk(dev);
> +	struct ublk_device *ub = disk->private_data;
> +	const struct ublk_param_uuid *p = &ub->params.uuid;
> +	uuid_t uuid;
> +
> +	import_uuid(&uuid, p->uuid);
> +	return sprintf(buf, "%pU\n", &uuid);
> +}
> +
> +static DEVICE_ATTR_RO(uuid);
> +
> +static struct attribute *ublk_attrs[] = {
> +	&dev_attr_uuid.attr,
> +	NULL,
> +};
> +
> +static umode_t ublk_attrs_are_visible(struct kobject *kobj,
> +		struct attribute *a, int n)
> +{
> +	struct device *dev = kobj_to_dev(kobj);
> +	struct gendisk *disk = dev_to_disk(dev);
> +	struct ublk_device *ub = disk->private_data;
> +
> +	if (a == &dev_attr_uuid.attr &&
> +	    (ub->params.types & UBLK_PARAM_TYPE_UUID))
> +		return S_IRUGO;
> +
> +	return a->mode;
> +}
> +
> +static const struct attribute_group ublk_attr_group = {
> +	.attrs = ublk_attrs,
> +	.is_visible = ublk_attrs_are_visible,
> +};
> +
> +static const struct attribute_group *ublk_attr_groups[] = {
> +	&ublk_attr_group,
> +	NULL,
> +};
> +
>  /* align max io buffer size with PAGE_SIZE */
>  static void ublk_align_max_io_size(struct ublk_device *ub)
>  {
> @@ -3149,7 +3200,7 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
>  			goto out_put_cdev;
>  	}
>  
> -	ret = add_disk(disk);
> +	ret = device_add_disk(NULL, disk, ublk_attr_groups);
>  	if (ret)
>  		goto out_put_cdev;
>  
> diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
> index 90f47da4f435..b30a0de44b85 100644
> --- a/include/uapi/linux/ublk_cmd.h
> +++ b/include/uapi/linux/ublk_cmd.h
> @@ -630,6 +630,10 @@ struct ublk_param_integrity {
>  	__u8	pad[5];
>  };
>  
> +struct ublk_param_uuid {
> +	__u8	uuid[16];
> +};
> +
>  struct ublk_params {
>  	/*
>  	 * Total length of parameters, userspace has to set 'len' for both
> @@ -645,6 +649,7 @@ struct ublk_params {
>  #define UBLK_PARAM_TYPE_DMA_ALIGN       (1 << 4)
>  #define UBLK_PARAM_TYPE_SEGMENT         (1 << 5)
>  #define UBLK_PARAM_TYPE_INTEGRITY       (1 << 6) /* requires UBLK_F_INTEGRITY */
> +#define UBLK_PARAM_TYPE_UUID            (1 << 7)
>  	__u32	types;			/* types of parameter included */
>  
>  	struct ublk_param_basic		basic;
> @@ -654,6 +659,7 @@ struct ublk_params {
>  	struct ublk_param_dma_align	dma;
>  	struct ublk_param_segment	seg;
>  	struct ublk_param_integrity	integrity;
> +	struct ublk_param_uuid		uuid;

It could be more friendly for ublk server writer to document that `uuid`
parameter should be persistent, otherwise:

Reviewed-by: Ming Lei <ming.lei@redhat.com>


Thanks,
Ming


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

end of thread, other threads:[~2026-02-20 16:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-20 15:06 [PATCHv2] ublk: persistent device links Hannes Reinecke
2026-02-20 16:16 ` Ming Lei

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox