Skip to content

Commit 8722d70

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 44affbe commit 8722d70

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

drivers/block/ublk_drv.c

Lines changed: 42 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

@@ -919,6 +922,9 @@ static int ublk_open(struct gendisk *disk, blk_mode_t mode)
919922
return -EPERM;
920923
}
921924

925+
if (ub->block_open)
926+
return -EBUSY;
927+
922928
return 0;
923929
}
924930

@@ -3309,6 +3315,38 @@ static void ublk_ctrl_stop_dev(struct ublk_device *ub)
33093315
ublk_stop_dev(ub);
33103316
}
33113317

3318+
static int ublk_ctrl_try_stop_dev(struct ublk_device *ub)
3319+
{
3320+
struct gendisk *disk;
3321+
int ret = -EINVAL;
3322+
3323+
disk = ublk_get_disk(ub);
3324+
if (!disk) {
3325+
ret = -ENODEV;
3326+
goto out;
3327+
}
3328+
3329+
mutex_lock(&disk->open_mutex);
3330+
if (disk_openers(disk) > 0) {
3331+
ret = -EBUSY;
3332+
goto unlock;
3333+
}
3334+
ub->block_open = true;
3335+
/* release open_mutex as del_gendisk() will reacquire it */
3336+
mutex_unlock(&disk->open_mutex);
3337+
3338+
ublk_ctrl_stop_dev(ub);
3339+
ret = 0;
3340+
goto put_disk;
3341+
3342+
unlock:
3343+
mutex_unlock(&disk->open_mutex);
3344+
put_disk:
3345+
ublk_put_disk(disk);
3346+
out:
3347+
return ret;
3348+
}
3349+
33123350
static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
33133351
const struct ublksrv_ctrl_cmd *header)
33143352
{
@@ -3704,6 +3742,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
37043742
case UBLK_CMD_END_USER_RECOVERY:
37053743
case UBLK_CMD_UPDATE_SIZE:
37063744
case UBLK_CMD_QUIESCE_DEV:
3745+
case UBLK_CMD_TRY_STOP_DEV:
37073746
mask = MAY_READ | MAY_WRITE;
37083747
break;
37093748
default:
@@ -3817,6 +3856,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
38173856
case UBLK_CMD_QUIESCE_DEV:
38183857
ret = ublk_ctrl_quiesce_dev(ub, header);
38193858
break;
3859+
case UBLK_CMD_TRY_STOP_DEV:
3860+
ret = ublk_ctrl_try_stop_dev(ub);
3861+
break;
38203862
default:
38213863
ret = -EOPNOTSUPP;
38223864
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)