ublk: Add UBLK_U_CMD_UPDATE_SIZE
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. Signed-off-by: Omri Mann <omri@nvidia.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/2a370ab1-d85b-409d-b762-f9f3f6bdf705@nvidia.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
033b667a82
commit
98b995660b
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
/* private ioctl command mirror */
|
||||
#define UBLK_CMD_DEL_DEV_ASYNC _IOC_NR(UBLK_U_CMD_DEL_DEV_ASYNC)
|
||||
#define UBLK_CMD_UPDATE_SIZE _IOC_NR(UBLK_U_CMD_UPDATE_SIZE)
|
||||
|
||||
#define UBLK_IO_REGISTER_IO_BUF _IOC_NR(UBLK_U_IO_REGISTER_IO_BUF)
|
||||
#define UBLK_IO_UNREGISTER_IO_BUF _IOC_NR(UBLK_U_IO_UNREGISTER_IO_BUF)
|
||||
|
|
@ -64,7 +65,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 \
|
||||
|
|
@ -3075,6 +3077,16 @@ static int ublk_ctrl_get_features(const struct ublksrv_ctrl_cmd *header)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ublk_ctrl_set_size(struct ublk_device *ub, const struct ublksrv_ctrl_cmd *header)
|
||||
{
|
||||
struct ublk_param_basic *p = &ub->params.basic;
|
||||
u64 new_size = 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
|
||||
|
|
@ -3160,6 +3172,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 UBLK_CMD_UPDATE_SIZE:
|
||||
mask = MAY_READ | MAY_WRITE;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -3251,6 +3264,10 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
|
|||
case UBLK_CMD_END_USER_RECOVERY:
|
||||
ret = ublk_ctrl_end_recovery(ub, header);
|
||||
break;
|
||||
case UBLK_CMD_UPDATE_SIZE:
|
||||
ublk_ctrl_set_size(ub, header);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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,12 @@
|
|||
*/
|
||||
#define UBLK_F_USER_RECOVERY_FAIL_IO (1ULL << 9)
|
||||
|
||||
/*
|
||||
* Resizing a block device is possible with UBLK_U_CMD_UPDATE_SIZE
|
||||
* New size is passed in cmd->data[0] and is in units of sectors
|
||||
*/
|
||||
#define UBLK_F_UPDATE_SIZE (1ULL << 10)
|
||||
|
||||
/* device state */
|
||||
#define UBLK_S_DEV_DEAD 0
|
||||
#define UBLK_S_DEV_LIVE 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue