Skip to content

Commit 3aa004a

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 fdf6ef2 commit 3aa004a

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)
@@ -238,6 +239,8 @@ struct ublk_device {
238239
pid_t ublksrv_tgid;
239240
struct delayed_work exit_work;
240241

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

@@ -3280,6 +3283,38 @@ static void ublk_ctrl_stop_dev(struct ublk_device *ub)
32803283
ublk_stop_dev(ub);
32813284
}
32823285

3286+
static int ublk_ctrl_try_stop_dev(struct ublk_device *ub)
3287+
{
3288+
struct gendisk *disk;
3289+
int ret = -EINVAL;
3290+
3291+
disk = ublk_get_disk(ub);
3292+
if (!disk) {
3293+
ret = -ENODEV;
3294+
goto out;
3295+
}
3296+
3297+
mutex_lock(&disk->open_mutex);
3298+
if (disk_openers(disk) > 0) {
3299+
ret = -EBUSY;
3300+
goto unlock;
3301+
}
3302+
ub->block_open = true;
3303+
/* release open_mutex as del_gendisk() will reacquire it */
3304+
mutex_unlock(&disk->open_mutex);
3305+
3306+
ublk_ctrl_stop_dev(ub);
3307+
ret = 0;
3308+
goto put_disk;
3309+
3310+
unlock:
3311+
mutex_unlock(&disk->open_mutex);
3312+
put_disk:
3313+
ublk_put_disk(disk);
3314+
out:
3315+
return ret;
3316+
}
3317+
32833318
static int ublk_ctrl_get_dev_info(struct ublk_device *ub,
32843319
const struct ublksrv_ctrl_cmd *header)
32853320
{
@@ -3675,6 +3710,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
36753710
case UBLK_CMD_END_USER_RECOVERY:
36763711
case UBLK_CMD_UPDATE_SIZE:
36773712
case UBLK_CMD_QUIESCE_DEV:
3713+
case UBLK_CMD_TRY_STOP_DEV:
36783714
mask = MAY_READ | MAY_WRITE;
36793715
break;
36803716
default:
@@ -3788,6 +3824,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
37883824
case UBLK_CMD_QUIESCE_DEV:
37893825
ret = ublk_ctrl_quiesce_dev(ub, header);
37903826
break;
3827+
case UBLK_CMD_TRY_STOP_DEV:
3828+
ret = ublk_ctrl_try_stop_dev(ub);
3829+
break;
37913830
default:
37923831
ret = -EOPNOTSUPP;
37933832
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)