Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: add UBLK_CMD_TRY_STOP_DEV command

Add a best-effort stop command, UBLK_CMD_TRY_STOP_DEV, which only stops a
ublk device when it has no active openers.

Unlike UBLK_CMD_STOP_DEV, this command does not disrupt existing users.
New opens are blocked only after disk_openers has reached zero; if the
device is busy, the command returns -EBUSY and leaves it running.

The ub->block_open flag is used only to close a race with an in-progress
open and does not otherwise change open behavior.

Advertise support via the UBLK_F_SAFE_STOP_DEV feature flag.

Signed-off-by: Yoav Cohen <yoav@nvidia.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Yoav Cohen and committed by
Jens Axboe
93ada1b3 9e386f49

+50 -3
+42 -2
drivers/block/ublk_drv.c
··· 56 56 #define UBLK_CMD_DEL_DEV_ASYNC _IOC_NR(UBLK_U_CMD_DEL_DEV_ASYNC) 57 57 #define UBLK_CMD_UPDATE_SIZE _IOC_NR(UBLK_U_CMD_UPDATE_SIZE) 58 58 #define UBLK_CMD_QUIESCE_DEV _IOC_NR(UBLK_U_CMD_QUIESCE_DEV) 59 + #define UBLK_CMD_TRY_STOP_DEV _IOC_NR(UBLK_U_CMD_TRY_STOP_DEV) 59 60 60 61 #define UBLK_IO_REGISTER_IO_BUF _IOC_NR(UBLK_U_IO_REGISTER_IO_BUF) 61 62 #define UBLK_IO_UNREGISTER_IO_BUF _IOC_NR(UBLK_U_IO_UNREGISTER_IO_BUF) ··· 77 76 | UBLK_F_QUIESCE \ 78 77 | UBLK_F_PER_IO_DAEMON \ 79 78 | UBLK_F_BUF_REG_OFF_DAEMON \ 80 - | (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) ? UBLK_F_INTEGRITY : 0)) 79 + | (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) ? UBLK_F_INTEGRITY : 0) \ 80 + | UBLK_F_SAFE_STOP_DEV) 81 81 82 82 #define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \ 83 83 | UBLK_F_USER_RECOVERY_REISSUE \ ··· 244 242 pid_t ublksrv_tgid; 245 243 struct delayed_work exit_work; 246 244 struct work_struct partition_scan_work; 245 + 246 + bool block_open; /* protected by open_mutex */ 247 247 248 248 struct ublk_queue *queues[]; 249 249 }; ··· 987 983 ub->dev_info.owner_gid) 988 984 return -EPERM; 989 985 } 986 + 987 + if (ub->block_open) 988 + return -ENXIO; 990 989 991 990 return 0; 992 991 } ··· 3350 3343 ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE | 3351 3344 UBLK_F_URING_CMD_COMP_IN_TASK | 3352 3345 UBLK_F_PER_IO_DAEMON | 3353 - UBLK_F_BUF_REG_OFF_DAEMON; 3346 + UBLK_F_BUF_REG_OFF_DAEMON | 3347 + UBLK_F_SAFE_STOP_DEV; 3354 3348 3355 3349 /* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */ 3356 3350 if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY | ··· 3470 3462 static void ublk_ctrl_stop_dev(struct ublk_device *ub) 3471 3463 { 3472 3464 ublk_stop_dev(ub); 3465 + } 3466 + 3467 + static int ublk_ctrl_try_stop_dev(struct ublk_device *ub) 3468 + { 3469 + struct gendisk *disk; 3470 + int ret = 0; 3471 + 3472 + disk = ublk_get_disk(ub); 3473 + if (!disk) 3474 + return -ENODEV; 3475 + 3476 + mutex_lock(&disk->open_mutex); 3477 + if (disk_openers(disk) > 0) { 3478 + ret = -EBUSY; 3479 + goto unlock; 3480 + } 3481 + ub->block_open = true; 3482 + /* release open_mutex as del_gendisk() will reacquire it */ 3483 + mutex_unlock(&disk->open_mutex); 3484 + 3485 + ublk_ctrl_stop_dev(ub); 3486 + goto out; 3487 + 3488 + unlock: 3489 + mutex_unlock(&disk->open_mutex); 3490 + out: 3491 + ublk_put_disk(disk); 3492 + return ret; 3473 3493 } 3474 3494 3475 3495 static int ublk_ctrl_get_dev_info(struct ublk_device *ub, ··· 3895 3859 case UBLK_CMD_END_USER_RECOVERY: 3896 3860 case UBLK_CMD_UPDATE_SIZE: 3897 3861 case UBLK_CMD_QUIESCE_DEV: 3862 + case UBLK_CMD_TRY_STOP_DEV: 3898 3863 mask = MAY_READ | MAY_WRITE; 3899 3864 break; 3900 3865 default: ··· 4008 3971 break; 4009 3972 case UBLK_CMD_QUIESCE_DEV: 4010 3973 ret = ublk_ctrl_quiesce_dev(ub, header); 3974 + break; 3975 + case UBLK_CMD_TRY_STOP_DEV: 3976 + ret = ublk_ctrl_try_stop_dev(ub); 4011 3977 break; 4012 3978 default: 4013 3979 ret = -EOPNOTSUPP;
+8 -1
include/uapi/linux/ublk_cmd.h
··· 55 55 _IOWR('u', 0x15, struct ublksrv_ctrl_cmd) 56 56 #define UBLK_U_CMD_QUIESCE_DEV \ 57 57 _IOWR('u', 0x16, struct ublksrv_ctrl_cmd) 58 - 58 + #define UBLK_U_CMD_TRY_STOP_DEV \ 59 + _IOWR('u', 0x17, struct ublksrv_ctrl_cmd) 59 60 /* 60 61 * 64bits are enough now, and it should be easy to extend in case of 61 62 * running out of feature flags ··· 321 320 * Requires UBLK_F_USER_COPY. 322 321 */ 323 322 #define UBLK_F_INTEGRITY (1ULL << 16) 323 + 324 + /* 325 + * The device supports the UBLK_CMD_TRY_STOP_DEV command, which 326 + * allows stopping the device only if there are no openers. 327 + */ 328 + #define UBLK_F_SAFE_STOP_DEV (1ULL << 17) 324 329 325 330 /* device state */ 326 331 #define UBLK_S_DEV_DEAD 0