public inbox for linux-block@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] ublk: introduce UBLK_CMD_TRY_STOP_DEV
@ 2026-01-04  8:48 Yoav Cohen
  2026-01-04  8:48 ` [PATCH v2 1/2] ublk: make ublk_ctrl_stop_dev return void Yoav Cohen
  2026-01-04  8:48 ` [PATCH v2 2/2] ublk: add UBLK_CMD_TRY_STOP_DEV command Yoav Cohen
  0 siblings, 2 replies; 5+ messages in thread
From: Yoav Cohen @ 2026-01-04  8:48 UTC (permalink / raw)
  To: linux-block, csander, ming.lei; +Cc: jholzman, omril, Yoav Cohen

Hello,

This patch series introduces a new command for ublk device management.

The first patch changes `ublk_ctrl_stop_dev()` to return void, since it
always returned 0. This simplifies the API.

The second patch introduces `UBLK_CMD_TRY_STOP_DEV`, which stops the
device only if there are no active openers. Unlike the existing stop
command (`UBLK_CMD_STOP_DEV`), this command avoids disrupting active
users by returning -EBUSY if the device is busy.

These patches only introduce the new command and API simplification
without altering existing behavior for active users.

Yoav Cohen (2):
  ublk: make ublk_ctrl_stop_dev return void
  ublk: add UBLK_CMD_TRY_STOP_DEV command

 drivers/block/ublk_drv.c      | 48 ++++++++++++++++++++++++++++++++---
 include/uapi/linux/ublk_cmd.h |  3 ++-
 2 files changed, 47 insertions(+), 4 deletions(-)

-- 
2.39.5 (Apple Git-154)


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

* [PATCH v2 1/2] ublk: make ublk_ctrl_stop_dev return void
  2026-01-04  8:48 [PATCH v2 0/2] ublk: introduce UBLK_CMD_TRY_STOP_DEV Yoav Cohen
@ 2026-01-04  8:48 ` Yoav Cohen
  2026-01-06 14:14   ` Ming Lei
  2026-01-04  8:48 ` [PATCH v2 2/2] ublk: add UBLK_CMD_TRY_STOP_DEV command Yoav Cohen
  1 sibling, 1 reply; 5+ messages in thread
From: Yoav Cohen @ 2026-01-04  8:48 UTC (permalink / raw)
  To: linux-block, csander, ming.lei; +Cc: jholzman, omril, Yoav Cohen

This function always returns 0, so there is no need to return a value.

Signed-off-by: Yoav Cohen <yoav@nvidia.com>
---
 drivers/block/ublk_drv.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 837fedb02e0d..2d5602ef05cc 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -3304,10 +3304,9 @@ static inline void ublk_ctrl_cmd_dump(struct io_uring_cmd *cmd)
 			header->data[0], header->addr, header->len);
 }
 
-static int ublk_ctrl_stop_dev(struct ublk_device *ub)
+static void ublk_ctrl_stop_dev(struct ublk_device *ub)
 {
 	ublk_stop_dev(ub);
-	return 0;
 }
 
 static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
@@ -3780,7 +3779,8 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
 		ret = ublk_ctrl_start_dev(ub, header);
 		break;
 	case UBLK_CMD_STOP_DEV:
-		ret = ublk_ctrl_stop_dev(ub);
+		ublk_ctrl_stop_dev(ub);
+		ret = 0;
 		break;
 	case UBLK_CMD_GET_DEV_INFO:
 	case UBLK_CMD_GET_DEV_INFO2:
-- 
2.39.5 (Apple Git-154)


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

* [PATCH v2 2/2] ublk: add UBLK_CMD_TRY_STOP_DEV command
  2026-01-04  8:48 [PATCH v2 0/2] ublk: introduce UBLK_CMD_TRY_STOP_DEV Yoav Cohen
  2026-01-04  8:48 ` [PATCH v2 1/2] ublk: make ublk_ctrl_stop_dev return void Yoav Cohen
@ 2026-01-04  8:48 ` Yoav Cohen
  2026-01-06 14:28   ` Ming Lei
  1 sibling, 1 reply; 5+ messages in thread
From: Yoav Cohen @ 2026-01-04  8:48 UTC (permalink / raw)
  To: linux-block, csander, ming.lei; +Cc: jholzman, omril, Yoav Cohen

This command is similar to UBLK_CMD_STOP_DEV, but it only stops the
device if there are no active openers for the ublk block device.
If the device is busy, the command returns -EBUSY instead of
disrupting active clients. This allows safe, non-destructive stopping.

Signed-off-by: Yoav Cohen <yoav@nvidia.com>
---
 drivers/block/ublk_drv.c      | 42 +++++++++++++++++++++++++++++++++++
 include/uapi/linux/ublk_cmd.h |  3 ++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 2d5602ef05cc..55a5ab11c1cd 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -54,6 +54,7 @@
 #define UBLK_CMD_DEL_DEV_ASYNC	_IOC_NR(UBLK_U_CMD_DEL_DEV_ASYNC)
 #define UBLK_CMD_UPDATE_SIZE	_IOC_NR(UBLK_U_CMD_UPDATE_SIZE)
 #define UBLK_CMD_QUIESCE_DEV	_IOC_NR(UBLK_U_CMD_QUIESCE_DEV)
+#define UBLK_CMD_TRY_STOP_DEV	_IOC_NR(UBLK_U_CMD_TRY_STOP_DEV)
 
 #define UBLK_IO_REGISTER_IO_BUF		_IOC_NR(UBLK_U_IO_REGISTER_IO_BUF)
 #define UBLK_IO_UNREGISTER_IO_BUF	_IOC_NR(UBLK_U_IO_UNREGISTER_IO_BUF)
@@ -239,6 +240,8 @@ struct ublk_device {
 	struct delayed_work	exit_work;
 	struct work_struct	partition_scan_work;
 
+	bool			block_open; /* protected by open_mutex */
+
 	struct ublk_queue       *queues[];
 };
 
@@ -919,6 +922,9 @@ static int ublk_open(struct gendisk *disk, blk_mode_t mode)
 			return -EPERM;
 	}
 
+	if (ub->block_open)
+		return -EBUSY;
+
 	return 0;
 }
 
@@ -3309,6 +3315,38 @@ static void ublk_ctrl_stop_dev(struct ublk_device *ub)
 	ublk_stop_dev(ub);
 }
 
+static int ublk_ctrl_try_stop_dev(struct ublk_device *ub)
+{
+	struct gendisk *disk;
+	int ret = -EINVAL;
+
+	disk = ublk_get_disk(ub);
+	if (!disk) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	mutex_lock(&disk->open_mutex);
+	if (disk_openers(disk) > 0) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+	ub->block_open = true;
+	/* release open_mutex as del_gendisk() will reacquire it */
+	mutex_unlock(&disk->open_mutex);
+
+	ublk_ctrl_stop_dev(ub);
+	ret = 0;
+	goto put_disk;
+
+unlock:
+	mutex_unlock(&disk->open_mutex);
+put_disk:
+	ublk_put_disk(disk);
+out:
+	return ret;
+}
+
 static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
 		const struct ublksrv_ctrl_cmd *header)
 {
@@ -3704,6 +3742,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
 	case UBLK_CMD_END_USER_RECOVERY:
 	case UBLK_CMD_UPDATE_SIZE:
 	case UBLK_CMD_QUIESCE_DEV:
+	case UBLK_CMD_TRY_STOP_DEV:
 		mask = MAY_READ | MAY_WRITE;
 		break;
 	default:
@@ -3817,6 +3856,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
 	case UBLK_CMD_QUIESCE_DEV:
 		ret = ublk_ctrl_quiesce_dev(ub, header);
 		break;
+	case UBLK_CMD_TRY_STOP_DEV:
+		ret = ublk_ctrl_try_stop_dev(ub);
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		break;
diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
index ec77dabba45b..bb191d0afff7 100644
--- a/include/uapi/linux/ublk_cmd.h
+++ b/include/uapi/linux/ublk_cmd.h
@@ -55,7 +55,8 @@
 	_IOWR('u', 0x15, struct ublksrv_ctrl_cmd)
 #define UBLK_U_CMD_QUIESCE_DEV		\
 	_IOWR('u', 0x16, struct ublksrv_ctrl_cmd)
-
+#define UBLK_U_CMD_TRY_STOP_DEV		\
+	_IOWR('u', 0x17, struct ublksrv_ctrl_cmd)
 /*
  * 64bits are enough now, and it should be easy to extend in case of
  * running out of feature flags
-- 
2.39.5 (Apple Git-154)


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

* Re: [PATCH v2 1/2] ublk: make ublk_ctrl_stop_dev return void
  2026-01-04  8:48 ` [PATCH v2 1/2] ublk: make ublk_ctrl_stop_dev return void Yoav Cohen
@ 2026-01-06 14:14   ` Ming Lei
  0 siblings, 0 replies; 5+ messages in thread
From: Ming Lei @ 2026-01-06 14:14 UTC (permalink / raw)
  To: Yoav Cohen; +Cc: linux-block, csander, jholzman, omril

On Sun, Jan 04, 2026 at 10:48:38AM +0200, Yoav Cohen wrote:
> This function always returns 0, so there is no need to return a value.
> 
> Signed-off-by: Yoav Cohen <yoav@nvidia.com>
> ---
>  drivers/block/ublk_drv.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 837fedb02e0d..2d5602ef05cc 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -3304,10 +3304,9 @@ static inline void ublk_ctrl_cmd_dump(struct io_uring_cmd *cmd)
>  			header->data[0], header->addr, header->len);
>  }
>  
> -static int ublk_ctrl_stop_dev(struct ublk_device *ub)
> +static void ublk_ctrl_stop_dev(struct ublk_device *ub)
>  {
>  	ublk_stop_dev(ub);
> -	return 0;
>  }
>  
>  static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
> @@ -3780,7 +3779,8 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
>  		ret = ublk_ctrl_start_dev(ub, header);
>  		break;
>  	case UBLK_CMD_STOP_DEV:
> -		ret = ublk_ctrl_stop_dev(ub);
> +		ublk_ctrl_stop_dev(ub);
> +		ret = 0;

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


Thanks
Ming


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

* Re: [PATCH v2 2/2] ublk: add UBLK_CMD_TRY_STOP_DEV command
  2026-01-04  8:48 ` [PATCH v2 2/2] ublk: add UBLK_CMD_TRY_STOP_DEV command Yoav Cohen
@ 2026-01-06 14:28   ` Ming Lei
  0 siblings, 0 replies; 5+ messages in thread
From: Ming Lei @ 2026-01-06 14:28 UTC (permalink / raw)
  To: Yoav Cohen; +Cc: linux-block, csander, jholzman, omril

On Sun, Jan 04, 2026 at 10:48:39AM +0200, Yoav Cohen wrote:
> This command is similar to UBLK_CMD_STOP_DEV, but it only stops the
> device if there are no active openers for the ublk block device.
> If the device is busy, the command returns -EBUSY instead of
> disrupting active clients. This allows safe, non-destructive stopping.
> 
> Signed-off-by: Yoav Cohen <yoav@nvidia.com>
> ---
>  drivers/block/ublk_drv.c      | 42 +++++++++++++++++++++++++++++++++++
>  include/uapi/linux/ublk_cmd.h |  3 ++-
>  2 files changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 2d5602ef05cc..55a5ab11c1cd 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -54,6 +54,7 @@
>  #define UBLK_CMD_DEL_DEV_ASYNC	_IOC_NR(UBLK_U_CMD_DEL_DEV_ASYNC)
>  #define UBLK_CMD_UPDATE_SIZE	_IOC_NR(UBLK_U_CMD_UPDATE_SIZE)
>  #define UBLK_CMD_QUIESCE_DEV	_IOC_NR(UBLK_U_CMD_QUIESCE_DEV)
> +#define UBLK_CMD_TRY_STOP_DEV	_IOC_NR(UBLK_U_CMD_TRY_STOP_DEV)

This need a feature flag, such as UBLK_F_SAFE_STOP, which is set in
ublk_ctrl_add_dev(), meantime document that UBLK_CMD_TRY_STOP_DEV is
supported with this feature.

>  
>  #define UBLK_IO_REGISTER_IO_BUF		_IOC_NR(UBLK_U_IO_REGISTER_IO_BUF)
>  #define UBLK_IO_UNREGISTER_IO_BUF	_IOC_NR(UBLK_U_IO_UNREGISTER_IO_BUF)
> @@ -239,6 +240,8 @@ struct ublk_device {
>  	struct delayed_work	exit_work;
>  	struct work_struct	partition_scan_work;
>  
> +	bool			block_open; /* protected by open_mutex */
> +
>  	struct ublk_queue       *queues[];
>  };
>  
> @@ -919,6 +922,9 @@ static int ublk_open(struct gendisk *disk, blk_mode_t mode)
>  			return -EPERM;
>  	}
>  
> +	if (ub->block_open)
> +		return -EBUSY;
> +
>  	return 0;
>  }
>  
> @@ -3309,6 +3315,38 @@ static void ublk_ctrl_stop_dev(struct ublk_device *ub)
>  	ublk_stop_dev(ub);
>  }
>  
> +static int ublk_ctrl_try_stop_dev(struct ublk_device *ub)
> +{
> +	struct gendisk *disk;
> +	int ret = -EINVAL;

-EINVAL is never used, it may save the line of `ret = 0` if it is
initialized as 0.

> +
> +	disk = ublk_get_disk(ub);
> +	if (!disk) {
> +		ret = -ENODEV;
> +		goto out;

		return -ENODEV;


Thanks, 
Ming


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

end of thread, other threads:[~2026-01-06 14:28 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-04  8:48 [PATCH v2 0/2] ublk: introduce UBLK_CMD_TRY_STOP_DEV Yoav Cohen
2026-01-04  8:48 ` [PATCH v2 1/2] ublk: make ublk_ctrl_stop_dev return void Yoav Cohen
2026-01-06 14:14   ` Ming Lei
2026-01-04  8:48 ` [PATCH v2 2/2] ublk: add UBLK_CMD_TRY_STOP_DEV command Yoav Cohen
2026-01-06 14:28   ` Ming Lei

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