Message ID | 36ba7ff3-ff0e-4db1-acb1-8e7a60a427cc@nvidia.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v3] : ublk: Add UBLK_U_CMD_UPDATE_SIZE | expand |
On Mon, Apr 14, 2025 at 4:45 AM Jared Holzman <jholzman@nvidia.com> wrote: > > Currently ublk only allows the size of the ublkb block device to be > set via UBLK_CMD_SET_PARAMS before UBLK_CMD_START_DEV is triggered. > > This does not provide support for extendable user-space block devices > without having to stop and restart the underlying ublkb block device > causing IO interruption. > > This patch adds a new ublk command UBLK_U_CMD_UPDATE_SIZE to allow the > ublk block device to be resized on-the-fly. > > Feature flag UBLK_F_UPDATE_SIZE is also added to indicate support for > this command. > > Signed-off-by: Omri Mann <omri@nvidia.com> > --- > drivers/block/ublk_drv.c | 19 ++++++++++++++++++- > include/uapi/linux/ublk_cmd.h | 7 +++++++ > 2 files changed, 25 insertions(+), 1 deletion(-) > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c > index 2fd05c1bd30b..2a8d8b864ef9 100644 > --- a/drivers/block/ublk_drv.c > +++ b/drivers/block/ublk_drv.c > @@ -64,7 +64,8 @@ > | UBLK_F_CMD_IOCTL_ENCODE \ > | UBLK_F_USER_COPY \ > | UBLK_F_ZONED \ > - | UBLK_F_USER_RECOVERY_FAIL_IO) > + | UBLK_F_USER_RECOVERY_FAIL_IO \ > + | UBLK_F_UPDATE_SIZE) > > #define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \ > | UBLK_F_USER_RECOVERY_REISSUE \ > @@ -3052,6 +3053,17 @@ static int ublk_ctrl_get_features(struct > io_uring_cmd *cmd) > return 0; > } > > +static void ublk_ctrl_set_size(struct ublk_device *ub, struct > io_uring_cmd *cmd) > +{ > + const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe); Can you pass header instead of cmd to this function? See my recent commit changing most of the other ublk_ctrl handlers: https://git.kernel.dk/cgit/linux/commit/?h=block-6.15&id=843c6cec1af85f05971b7baf3704801895e77d76 > + struct ublk_param_basic *p = &ub->params.basic; > + size_t new_size = (int)header->data[0]; Why cast from u64 to int and back to size_t? > + > + mutex_lock(&ub->mutex); > + p->dev_sectors = new_size; > + set_capacity_and_notify(ub->ub_disk, p->dev_sectors); > + mutex_unlock(&ub->mutex); > +} > /* > * All control commands are sent via /dev/ublk-control, so we have to > check > * the destination device's permission > @@ -3137,6 +3149,7 @@ static int ublk_ctrl_uring_cmd_permission(struct > ublk_device *ub, > case UBLK_CMD_SET_PARAMS: > case UBLK_CMD_START_USER_RECOVERY: > case UBLK_CMD_END_USER_RECOVERY: > + case _IOC_NR(UBLK_U_CMD_UPDATE_SIZE): > mask = MAY_READ | MAY_WRITE; > break; > default: > @@ -3228,6 +3241,10 @@ static int ublk_ctrl_uring_cmd(struct > io_uring_cmd *cmd, > case UBLK_CMD_END_USER_RECOVERY: > ret = ublk_ctrl_end_recovery(ub, cmd); > break; > + case _IOC_NR(UBLK_U_CMD_UPDATE_SIZE): > + ublk_ctrl_set_size(ub, cmd); > + ret = 0; > + break; > default: > ret = -EOPNOTSUPP; > break; > diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h > index 583b86681c93..0e40e497c28f 100644 > --- a/include/uapi/linux/ublk_cmd.h > +++ b/include/uapi/linux/ublk_cmd.h > @@ -51,6 +51,8 @@ > _IOR('u', 0x13, struct ublksrv_ctrl_cmd) > #define UBLK_U_CMD_DEL_DEV_ASYNC \ > _IOR('u', 0x14, struct ublksrv_ctrl_cmd) > +#define UBLK_U_CMD_UPDATE_SIZE \ > + _IOWR('u', 0x15, struct ublksrv_ctrl_cmd) > > /* > * 64bits are enough now, and it should be easy to extend in case of > @@ -211,6 +213,11 @@ > */ > #define UBLK_F_USER_RECOVERY_FAIL_IO (1ULL << 9) > > +/* > + * Resisizing a block device is possible with UBLK_U_CMD_UPDATE_SIZE "Resisizing" -> "Resizing"? Best, Caleb > + */ > +#define UBLK_F_UPDATE_SIZE (1ULL << 10) > + > /* device state */ > #define UBLK_S_DEV_DEAD 0 > #define UBLK_S_DEV_LIVE 1 > -- > 2.43.0 > >
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 2fd05c1bd30b..2a8d8b864ef9 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -64,7 +64,8 @@ | UBLK_F_CMD_IOCTL_ENCODE \ | UBLK_F_USER_COPY \ | UBLK_F_ZONED \ - | UBLK_F_USER_RECOVERY_FAIL_IO) + | UBLK_F_USER_RECOVERY_FAIL_IO \ + | UBLK_F_UPDATE_SIZE) #define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \ | UBLK_F_USER_RECOVERY_REISSUE \ @@ -3052,6 +3053,17 @@ static int ublk_ctrl_get_features(struct io_uring_cmd *cmd) return 0; } +static void ublk_ctrl_set_size(struct ublk_device *ub, struct io_uring_cmd *cmd) +{ + const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe); + struct ublk_param_basic *p = &ub->params.basic; + size_t new_size = (int)header->data[0]; + + mutex_lock(&ub->mutex); + p->dev_sectors = new_size; + set_capacity_and_notify(ub->ub_disk, p->dev_sectors); + mutex_unlock(&ub->mutex); +} /* * All control commands are sent via /dev/ublk-control, so we have to check * the destination device's permission @@ -3137,6 +3149,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub, case UBLK_CMD_SET_PARAMS: case UBLK_CMD_START_USER_RECOVERY: case UBLK_CMD_END_USER_RECOVERY: + case _IOC_NR(UBLK_U_CMD_UPDATE_SIZE): mask = MAY_READ | MAY_WRITE; break; default: @@ -3228,6 +3241,10 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, case UBLK_CMD_END_USER_RECOVERY: ret = ublk_ctrl_end_recovery(ub, cmd); break; + case _IOC_NR(UBLK_U_CMD_UPDATE_SIZE): + ublk_ctrl_set_size(ub, cmd); + ret = 0; + break; default: ret = -EOPNOTSUPP; break; diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h index 583b86681c93..0e40e497c28f 100644 --- a/include/uapi/linux/ublk_cmd.h +++ b/include/uapi/linux/ublk_cmd.h @@ -51,6 +51,8 @@ _IOR('u', 0x13, struct ublksrv_ctrl_cmd) #define UBLK_U_CMD_DEL_DEV_ASYNC \ _IOR('u', 0x14, struct ublksrv_ctrl_cmd) +#define UBLK_U_CMD_UPDATE_SIZE \ + _IOWR('u', 0x15, struct ublksrv_ctrl_cmd) /* * 64bits are enough now, and it should be easy to extend in case of @@ -211,6 +213,11 @@ */ #define UBLK_F_USER_RECOVERY_FAIL_IO (1ULL << 9) +/* + * Resisizing a block device is possible with UBLK_U_CMD_UPDATE_SIZE + */ +#define UBLK_F_UPDATE_SIZE (1ULL << 10) + /* device state */ #define UBLK_S_DEV_DEAD 0 #define UBLK_S_DEV_LIVE 1
Currently ublk only allows the size of the ublkb block device to be set via UBLK_CMD_SET_PARAMS before UBLK_CMD_START_DEV is triggered. This does not provide support for extendable user-space block devices without having to stop and restart the underlying ublkb block device causing IO interruption. This patch adds a new ublk command UBLK_U_CMD_UPDATE_SIZE to allow the ublk block device to be resized on-the-fly. Feature flag UBLK_F_UPDATE_SIZE is also added to indicate support for this command. Signed-off-by: Omri Mann <omri@nvidia.com> --- drivers/block/ublk_drv.c | 19 ++++++++++++++++++- include/uapi/linux/ublk_cmd.h | 7 +++++++ 2 files changed, 25 insertions(+), 1 deletion(-)