Re: [PATCH V5 4/6] ublk: support UBLK_AUTO_BUF_REG_FALLBACK

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, May 19, 2025 at 9:55 PM Ming Lei <ming.lei@xxxxxxxxxx> wrote:
>
> For UBLK_F_AUTO_BUF_REG, buffer is registered to uring_cmd context
> automatically with the provided buffer index. User may provide one wrong
> buffer index, or the specified buffer is registered by application already.
>
> Add UBLK_AUTO_BUF_REG_FALLBACK for supporting to auto buffer registering
> fallback by completing the uring_cmd and telling ublk server the
> register failure via UBLK_AUTO_BUF_REG_FALLBACK, then ublk server still
> can register the buffer from userspace.
>
> So we can provide reliable way for supporting auto buffer register.
>
> Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx>
> ---
>  drivers/block/ublk_drv.c      | 16 ++++++++++++++
>  include/uapi/linux/ublk_cmd.h | 39 ++++++++++++++++++++++++++++++++---
>  2 files changed, 52 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 1aabc655652b..2474788ef263 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -1182,6 +1182,16 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
>                 blk_mq_end_request(rq, BLK_STS_IOERR);
>  }
>
> +static void ublk_auto_buf_reg_fallback(struct request *req, struct ublk_io *io)

struct ublk_io *io appears unused.

> +{
> +       const struct ublk_queue *ubq = req->mq_hctx->driver_data;
> +       struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
> +       struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
> +
> +       iod->op_flags |= UBLK_IO_F_NEED_REG_BUF;
> +       refcount_set(&data->ref, 1);
> +}
> +
>  static bool ublk_auto_buf_reg(struct request *req, struct ublk_io *io,
>                               unsigned int issue_flags)
>  {
> @@ -1192,6 +1202,10 @@ static bool ublk_auto_buf_reg(struct request *req, struct ublk_io *io,
>         ret = io_buffer_register_bvec(io->cmd, req, ublk_io_release,
>                                       pdu->buf.index, issue_flags);
>         if (ret) {
> +               if (pdu->buf.flags & UBLK_AUTO_BUF_REG_FALLBACK) {
> +                       ublk_auto_buf_reg_fallback(req, io);
> +                       return true;
> +               }
>                 blk_mq_end_request(req, BLK_STS_IOERR);
>                 return false;
>         }
> @@ -1971,6 +1985,8 @@ static inline int ublk_set_auto_buf_reg(struct io_uring_cmd *cmd)
>         if (pdu->buf.reserved0 || pdu->buf.reserved1)
>                 return -EINVAL;
>
> +       if (pdu->buf.flags & ~UBLK_AUTO_BUF_REG_F_MASK)
> +               return -EINVAL;
>         return 0;
>  }
>
> diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
> index f6f516b1223b..c4b9942697fc 100644
> --- a/include/uapi/linux/ublk_cmd.h
> +++ b/include/uapi/linux/ublk_cmd.h
> @@ -236,9 +236,16 @@
>   *
>   * - all reserved fields in `ublk_auto_buf_reg` need to be zeroed
>   *
> + * - pass flags from `ublk_auto_buf_reg.flags` if needed
> + *
>   * This way avoids extra cost from two uring_cmd, but also simplifies backend
>   * implementation, such as, the dependency on IO_REGISTER_IO_BUF and
>   * IO_UNREGISTER_IO_BUF becomes not necessary.
> + *
> + * If wrong data or flags are provided, both IO_FETCH_REQ and
> + * IO_COMMIT_AND_FETCH_REQ are failed, for the latter, the ublk IO request
> + * won't be completed until new IO_COMMIT_AND_FETCH_REQ command is issued
> + * successfully

This part of the comment belongs in the previous commit adding
UBLK_F_AUTO_BUF_REG, right? It doesn't seem specific to
UBLK_AUTO_BUF_REG_FALLBACK.

Otherwise,
Reviewed-by: Caleb Sander Mateos <csander@xxxxxxxxxxxxxxx>

>   */
>  #define UBLK_F_AUTO_BUF_REG    (1ULL << 11)
>
> @@ -328,6 +335,17 @@ struct ublksrv_ctrl_dev_info {
>  #define                UBLK_IO_F_FUA                   (1U << 13)
>  #define                UBLK_IO_F_NOUNMAP               (1U << 15)
>  #define                UBLK_IO_F_SWAP                  (1U << 16)
> +/*
> + * For UBLK_F_AUTO_BUF_REG & UBLK_AUTO_BUF_REG_FALLBACK only.
> + *
> + * This flag is set if auto buffer register is failed & ublk server passes
> + * UBLK_AUTO_BUF_REG_FALLBACK, and ublk server need to register buffer
> + * manually for handling the delivered IO command if this flag is observed
> + *
> + * ublk server has to check this flag if UBLK_AUTO_BUF_REG_FALLBACK is
> + * passed in.
> + */
> +#define                UBLK_IO_F_NEED_REG_BUF          (1U << 17)
>
>  /*
>   * io cmd is described by this structure, and stored in share memory, indexed
> @@ -362,10 +380,23 @@ static inline __u32 ublksrv_get_flags(const struct ublksrv_io_desc *iod)
>         return iod->op_flags >> 8;
>  }
>
> +/*
> + * If this flag is set, fallback by completing the uring_cmd and setting
> + * `UBLK_IO_F_NEED_REG_BUF` in case of auto-buf-register failure;
> + * otherwise the client ublk request is failed silently
> + *
> + * If ublk server passes this flag, it has to check if UBLK_IO_F_NEED_REG_BUF
> + * is set in `ublksrv_io_desc.op_flags`. If UBLK_IO_F_NEED_REG_BUF is set,
> + * ublk server needs to register io buffer manually for handling IO command.
> + */
> +#define UBLK_AUTO_BUF_REG_FALLBACK     (1 << 0)
> +#define UBLK_AUTO_BUF_REG_F_MASK       UBLK_AUTO_BUF_REG_FALLBACK
> +
>  struct ublk_auto_buf_reg {
>         /* index for registering the delivered request buffer */
>         __u16  index;
> -       __u16   reserved0;
> +       __u8   flags;
> +       __u8   reserved0;
>
>         /*
>          * io_ring FD can be passed via the reserve field in future for
> @@ -379,6 +410,7 @@ struct ublk_auto_buf_reg {
>   * uring_cmd's sqe->addr:
>   *
>   *     - bit0 ~ bit15: buffer index
> + *     - bit16 ~ bit23: flags
>   *     - bit24 ~ bit31: reserved0
>   *     - bit32 ~ bit63: reserved1
>   */
> @@ -387,7 +419,8 @@ static inline struct ublk_auto_buf_reg ublk_sqe_addr_to_auto_buf_reg(
>  {
>         struct ublk_auto_buf_reg reg = {
>                 .index = sqe_addr & 0xffff,
> -               .reserved0 = (sqe_addr >> 16) & 0xffff,
> +               .flags = (sqe_addr >> 16) & 0xff,
> +               .reserved0 = (sqe_addr >> 24) & 0xff,
>                 .reserved1 = sqe_addr >> 32,
>         };
>
> @@ -397,7 +430,7 @@ static inline struct ublk_auto_buf_reg ublk_sqe_addr_to_auto_buf_reg(
>  static inline __u64
>  ublk_auto_buf_reg_to_sqe_addr(const struct ublk_auto_buf_reg *buf)
>  {
> -       __u64 addr = buf->index | (__u64)buf->reserved0 << 16 |
> +       __u64 addr = buf->index | (__u64)buf->flags << 16 | (__u64)buf->reserved0 << 24 |
>                 (__u64)buf->reserved1 << 32;
>
>         return addr;
> --
> 2.47.0
>





[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux