Skip to content

Commit c2f932f

Browse files
yoavcohkawasaki
authored andcommitted
ublk: add UBLK_CMD_TRY_STOP_DEV command
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 <[email protected]>
1 parent c65a43e commit c2f932f

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

drivers/block/ublk_drv.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define UBLK_CMD_DEL_DEV_ASYNC _IOC_NR(UBLK_U_CMD_DEL_DEV_ASYNC)
5555
#define UBLK_CMD_UPDATE_SIZE _IOC_NR(UBLK_U_CMD_UPDATE_SIZE)
5656
#define UBLK_CMD_QUIESCE_DEV _IOC_NR(UBLK_U_CMD_QUIESCE_DEV)
57+
#define UBLK_CMD_TRY_STOP_DEV _IOC_NR(UBLK_U_CMD_TRY_STOP_DEV)
5758

5859
#define UBLK_IO_REGISTER_IO_BUF _IOC_NR(UBLK_U_IO_REGISTER_IO_BUF)
5960
#define UBLK_IO_UNREGISTER_IO_BUF _IOC_NR(UBLK_U_IO_UNREGISTER_IO_BUF)
@@ -239,6 +240,8 @@ struct ublk_device {
239240
struct delayed_work exit_work;
240241
struct work_struct partition_scan_work;
241242

243+
bool block_open; /* protected by open_mutex */
244+
242245
struct ublk_queue *queues[];
243246
};
244247

@@ -3309,6 +3312,38 @@ static void ublk_ctrl_stop_dev(struct ublk_device *ub)
33093312
ublk_stop_dev(ub);
33103313
}
33113314

3315+
static int ublk_ctrl_try_stop_dev(struct ublk_device *ub)
3316+
{
3317+
struct gendisk *disk;
3318+
int ret = -EINVAL;
3319+
3320+
disk = ublk_get_disk(ub);
3321+
if (!disk) {
3322+
ret = -ENODEV;
3323+
goto out;
3324+
}
3325+
3326+
mutex_lock(&disk->open_mutex);
3327+
if (disk_openers(disk) > 0) {
3328+
ret = -EBUSY;
3329+
goto unlock;
3330+
}
3331+
ub->block_open = true;
3332+
/* release open_mutex as del_gendisk() will reacquire it */
3333+
mutex_unlock(&disk->open_mutex);
3334+
3335+
ublk_ctrl_stop_dev(ub);
3336+
ret = 0;
3337+
goto put_disk;
3338+
3339+
unlock:
3340+
mutex_unlock(&disk->open_mutex);
3341+
put_disk:
3342+
ublk_put_disk(disk);
3343+
out:
3344+
return ret;
3345+
}
3346+
33123347
static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
33133348
const struct ublksrv_ctrl_cmd *header)
33143349
{
@@ -3704,6 +3739,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
37043739
case UBLK_CMD_END_USER_RECOVERY:
37053740
case UBLK_CMD_UPDATE_SIZE:
37063741
case UBLK_CMD_QUIESCE_DEV:
3742+
case UBLK_CMD_TRY_STOP_DEV:
37073743
mask = MAY_READ | MAY_WRITE;
37083744
break;
37093745
default:
@@ -3817,6 +3853,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
38173853
case UBLK_CMD_QUIESCE_DEV:
38183854
ret = ublk_ctrl_quiesce_dev(ub, header);
38193855
break;
3856+
case UBLK_CMD_TRY_STOP_DEV:
3857+
ret = ublk_ctrl_try_stop_dev(ub);
3858+
break;
38203859
default:
38213860
ret = -EOPNOTSUPP;
38223861
break;

include/uapi/linux/ublk_cmd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
_IOWR('u', 0x15, struct ublksrv_ctrl_cmd)
5656
#define UBLK_U_CMD_QUIESCE_DEV \
5757
_IOWR('u', 0x16, struct ublksrv_ctrl_cmd)
58-
58+
#define UBLK_U_CMD_TRY_STOP_DEV \
59+
_IOWR('u', 0x17, struct ublksrv_ctrl_cmd)
5960
/*
6061
* 64bits are enough now, and it should be easy to extend in case of
6162
* running out of feature flags

0 commit comments

Comments
 (0)