All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ming Lei <ming.lei@redhat.com>
To: Caleb Sander Mateos <csander@purestorage.com>
Cc: Jens Axboe <axboe@kernel.dk>, Shuah Khan <shuah@kernel.org>,
	linux-block@vger.kernel.org, linux-kselftest@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Stanley Zhang <stazhang@purestorage.com>,
	Uday Shankar <ushankar@purestorage.com>,
	"Martin K . Petersen" <martin.petersen@oracle.com>
Subject: Re: [PATCH v3 03/19] ublk: support UBLK_PARAM_TYPE_INTEGRITY in device creation
Date: Wed, 7 Jan 2026 08:15:00 +0800	[thread overview]
Message-ID: <aV2lhCLzISL0J-vH@fedora> (raw)
In-Reply-To: <CADUfDZpwRQv0yghG7S4ugNGc4X_b5bC=Za=+M-D36J5T46w64g@mail.gmail.com>

On Tue, Jan 06, 2026 at 08:32:08AM -0800, Caleb Sander Mateos wrote:
> On Tue, Jan 6, 2026 at 5:09 AM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > On Mon, Jan 05, 2026 at 05:57:35PM -0700, Caleb Sander Mateos wrote:
> > > From: Stanley Zhang <stazhang@purestorage.com>
> > >
> > > Add a feature flag UBLK_F_INTEGRITY for a ublk server to request
> > > integrity/metadata support when creating a ublk device. The ublk server
> > > can also check for the feature flag on the created device or the result
> > > of UBLK_U_CMD_GET_FEATURES to tell if the ublk driver supports it.
> > > UBLK_F_INTEGRITY requires UBLK_F_USER_COPY, as user copy is the only
> > > data copy mode initially supported for integrity data.
> > > Add UBLK_PARAM_TYPE_INTEGRITY and struct ublk_param_integrity to struct
> > > ublk_params to specify the integrity params of a ublk device.
> > > UBLK_PARAM_TYPE_INTEGRITY requires UBLK_F_INTEGRITY and a nonzero
> > > metadata_size. The LBMD_PI_CAP_* and LBMD_PI_CSUM_* values from the
> > > linux/fs.h UAPI header are used for the flags and csum_type fields.
> > > If the UBLK_PARAM_TYPE_INTEGRITY flag is set, validate the integrity
> > > parameters and apply them to the blk_integrity limits.
> > > The struct ublk_param_integrity validations are based on the checks in
> > > blk_validate_integrity_limits(). Any invalid parameters should be
> > > rejected before being applied to struct blk_integrity.
> > >
> > > Signed-off-by: Stanley Zhang <stazhang@purestorage.com>
> > > [csander: drop redundant pi_tuple_size field, use block metadata UAPI
> > >  constants, add param validation]
> > > Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
> > > ---
> > >  drivers/block/ublk_drv.c      | 94 ++++++++++++++++++++++++++++++++++-
> > >  include/uapi/linux/ublk_cmd.h | 18 +++++++
> > >  2 files changed, 111 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > > index 8e3da9b2b93a..066c6ae062a0 100644
> > > --- a/drivers/block/ublk_drv.c
> > > +++ b/drivers/block/ublk_drv.c
> > > @@ -42,10 +42,12 @@
> > >  #include <linux/mm.h>
> > >  #include <asm/page.h>
> > >  #include <linux/task_work.h>
> > >  #include <linux/namei.h>
> > >  #include <linux/kref.h>
> > > +#include <linux/blk-integrity.h>
> > > +#include <uapi/linux/fs.h>
> > >  #include <uapi/linux/ublk_cmd.h>
> > >
> > >  #define UBLK_MINORS          (1U << MINORBITS)
> > >
> > >  #define UBLK_INVALID_BUF_IDX         ((u16)-1)
> > > @@ -81,11 +83,12 @@
> > >
> > >  /* All UBLK_PARAM_TYPE_* should be included here */
> > >  #define UBLK_PARAM_TYPE_ALL                                \
> > >       (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \
> > >        UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED |    \
> > > -      UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT)
> > > +      UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT | \
> > > +      UBLK_PARAM_TYPE_INTEGRITY)
> > >
> > >  struct ublk_uring_cmd_pdu {
> > >       /*
> > >        * Store requests in same batch temporarily for queuing them to
> > >        * daemon context.
> > > @@ -628,10 +631,57 @@ static void ublk_dev_param_basic_apply(struct ublk_device *ub)
> > >               set_disk_ro(ub->ub_disk, true);
> > >
> > >       set_capacity(ub->ub_disk, p->dev_sectors);
> > >  }
> > >
> > > +static int ublk_integrity_flags(u32 flags)
> > > +{
> > > +     int ret_flags = 0;
> > > +
> > > +     if (flags & LBMD_PI_CAP_INTEGRITY) {
> > > +             flags &= ~LBMD_PI_CAP_INTEGRITY;
> > > +             ret_flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
> > > +     }
> > > +     if (flags & LBMD_PI_CAP_REFTAG) {
> > > +             flags &= ~LBMD_PI_CAP_REFTAG;
> > > +             ret_flags |= BLK_INTEGRITY_REF_TAG;
> > > +     }
> > > +     return flags ? -EINVAL : ret_flags;
> > > +}
> > > +
> > > +static int ublk_integrity_pi_tuple_size(u8 csum_type)
> > > +{
> > > +     switch (csum_type) {
> > > +     case LBMD_PI_CSUM_NONE:
> > > +             return 0;
> > > +     case LBMD_PI_CSUM_IP:
> > > +     case LBMD_PI_CSUM_CRC16_T10DIF:
> > > +             return 8;
> > > +     case LBMD_PI_CSUM_CRC64_NVME:
> > > +             return 16;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +}
> > > +
> > > +static enum blk_integrity_checksum ublk_integrity_csum_type(u8 csum_type)
> > > +{
> > > +     switch (csum_type) {
> > > +     case LBMD_PI_CSUM_NONE:
> > > +             return BLK_INTEGRITY_CSUM_NONE;
> > > +     case LBMD_PI_CSUM_IP:
> > > +             return BLK_INTEGRITY_CSUM_IP;
> > > +     case LBMD_PI_CSUM_CRC16_T10DIF:
> > > +             return BLK_INTEGRITY_CSUM_CRC;
> > > +     case LBMD_PI_CSUM_CRC64_NVME:
> > > +             return BLK_INTEGRITY_CSUM_CRC64;
> > > +     default:
> > > +             WARN_ON_ONCE(1);
> > > +             return BLK_INTEGRITY_CSUM_NONE;
> > > +     }
> > > +}
> > > +
> > >  static int ublk_validate_params(const struct ublk_device *ub)
> > >  {
> > >       /* basic param is the only one which must be set */
> > >       if (ub->params.types & UBLK_PARAM_TYPE_BASIC) {
> > >               const struct ublk_param_basic *p = &ub->params.basic;
> > > @@ -690,10 +740,33 @@ static int ublk_validate_params(const struct ublk_device *ub)
> > >                       return -EINVAL;
> > >               if (p->max_segment_size < UBLK_MIN_SEGMENT_SIZE)
> > >                       return -EINVAL;
> > >       }
> > >
> > > +     if (ub->params.types & UBLK_PARAM_TYPE_INTEGRITY) {
> > > +             const struct ublk_param_integrity *p = &ub->params.integrity;
> > > +             int pi_tuple_size = ublk_integrity_pi_tuple_size(p->csum_type);
> > > +             int flags = ublk_integrity_flags(p->flags);
> > > +
> > > +             if (!(ub->dev_info.flags & UBLK_F_INTEGRITY))
> > > +                     return -EINVAL;
> > > +             if (flags < 0)
> > > +                     return flags;
> > > +             if (pi_tuple_size < 0)
> > > +                     return pi_tuple_size;
> > > +             if (!p->metadata_size)
> > > +                     return -EINVAL;
> > > +             if (p->csum_type == LBMD_PI_CSUM_NONE &&
> > > +                 p->flags & LBMD_PI_CAP_REFTAG)
> > > +                     return -EINVAL;
> > > +             if (p->pi_offset + pi_tuple_size > p->metadata_size)
> > > +                     return -EINVAL;
> > > +             if (p->interval_exp < SECTOR_SHIFT ||
> > > +                 p->interval_exp > ub->params.basic.logical_bs_shift)
> > > +                     return -EINVAL;
> > > +     }
> > > +
> > >       return 0;
> > >  }
> > >
> > >  static void ublk_apply_params(struct ublk_device *ub)
> > >  {
> > > @@ -2941,10 +3014,25 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
> > >               lim.seg_boundary_mask = ub->params.seg.seg_boundary_mask;
> > >               lim.max_segment_size = ub->params.seg.max_segment_size;
> > >               lim.max_segments = ub->params.seg.max_segments;
> > >       }
> > >
> > > +     if (ub->params.types & UBLK_PARAM_TYPE_INTEGRITY) {
> > > +             const struct ublk_param_integrity *p = &ub->params.integrity;
> > > +             int pi_tuple_size = ublk_integrity_pi_tuple_size(p->csum_type);
> > > +
> > > +             lim.integrity = (struct blk_integrity) {
> > > +                     .flags = ublk_integrity_flags(p->flags),
> > > +                     .csum_type = ublk_integrity_csum_type(p->csum_type),
> > > +                     .metadata_size = p->metadata_size,
> > > +                     .pi_offset = p->pi_offset,
> > > +                     .interval_exp = p->interval_exp,
> > > +                     .tag_size = p->tag_size,
> > > +                     .pi_tuple_size = pi_tuple_size,
> > > +             };
> > > +     }
> > > +
> > >       if (wait_for_completion_interruptible(&ub->completion) != 0)
> > >               return -EINTR;
> > >
> > >       if (ub->ublksrv_tgid != ublksrv_pid)
> > >               return -EINVAL;
> > > @@ -3131,10 +3219,14 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
> > >               if (info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY |
> > >                                       UBLK_F_AUTO_BUF_REG))
> > >                       return -EINVAL;
> > >       }
> > >
> > > +     /* User copy is required to access integrity buffer */
> > > +     if (info.flags & UBLK_F_INTEGRITY && !(info.flags & UBLK_F_USER_COPY))
> > > +             return -EINVAL;
> > > +
> > >       /* the created device is always owned by current user */
> > >       ublk_store_owner_uid_gid(&info.owner_uid, &info.owner_gid);
> > >
> > >       if (header->dev_id != info.dev_id) {
> > >               pr_warn("%s: dev id not match %u %u\n",
> > > diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h
> > > index ec77dabba45b..a54c47832fa2 100644
> > > --- a/include/uapi/linux/ublk_cmd.h
> > > +++ b/include/uapi/linux/ublk_cmd.h
> > > @@ -309,10 +309,16 @@
> > >   * the I/O's daemon task. The q_id and tag of the registered buffer are required
> > >   * in UBLK_U_IO_UNREGISTER_IO_BUF's ublksrv_io_cmd.
> > >   */
> > >  #define UBLK_F_BUF_REG_OFF_DAEMON (1ULL << 14)
> > >
> > > +/*
> > > + * ublk device supports requests with integrity/metadata buffer.
> > > + * Requires UBLK_F_USER_COPY.
> > > + */
> > > +#define UBLK_F_INTEGRITY (1ULL << 16)
> > > +
> > >  /* device state */
> > >  #define UBLK_S_DEV_DEAD      0
> > >  #define UBLK_S_DEV_LIVE      1
> > >  #define UBLK_S_DEV_QUIESCED  2
> > >  #define UBLK_S_DEV_FAIL_IO   3
> > > @@ -598,10 +604,20 @@ struct ublk_param_segment {
> > >       __u32   max_segment_size;
> > >       __u16   max_segments;
> > >       __u8    pad[2];
> > >  };
> > >
> > > +struct ublk_param_integrity {
> > > +     __u32   flags; /* LBMD_PI_CAP_* from linux/fs.h */
> > > +     __u8    interval_exp;
> > > +     __u8    metadata_size; /* UBLK_PARAM_TYPE_INTEGRITY requires nonzero */
> > > +     __u8    pi_offset;
> > > +     __u8    csum_type; /* LBMD_PI_CSUM_* from linux/fs.h */
> > > +     __u8    tag_size;
> > > +     __u8    pad[7];
> > > +};
> >
> > Looks max_integrity_segments is missed, otherwise this patch is fine for me.
> 
> My thinking was that there isn't any reason why a ublk server would
> need to limit the number of integrity segments. The request integrity
> segments aren't directly exposed to the ublk server through user copy.
> And since zero copy isn't supported for integrity data, there's no
> concern about needing to align the ublk integrity limits with the
> backing device limits. What do you think?

Yeah, it isn't needed in current implementation, but things may change in
future.

How about adding it(__u16) to `ublk_param_integrity`? And document it is ignored for
user-copy based implementation. It is usually part of HW/SW interface wrt. PI.

Thanks,
Ming


  reply	other threads:[~2026-01-07  0:15 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-06  0:57 [PATCH v3 00/19] ublk: add support for integrity data Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 01/19] blk-integrity: take const pointer in blk_integrity_rq() Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 02/19] ublk: move ublk flag check functions earlier Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 03/19] ublk: support UBLK_PARAM_TYPE_INTEGRITY in device creation Caleb Sander Mateos
2026-01-06 13:09   ` Ming Lei
2026-01-06 16:32     ` Caleb Sander Mateos
2026-01-07  0:15       ` Ming Lei [this message]
2026-01-07  2:20         ` Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 04/19] ublk: set UBLK_IO_F_INTEGRITY in ublksrv_io_desc Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 05/19] ublk: add ublk_copy_user_bvec() helper Caleb Sander Mateos
2026-01-06 13:14   ` Ming Lei
2026-01-06  0:57 ` [PATCH v3 06/19] ublk: split out ublk_user_copy() helper Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 07/19] ublk: inline ublk_check_and_get_req() into ublk_user_copy() Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 08/19] ublk: move offset check out of __ublk_check_and_get_req() Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 09/19] ublk: implement integrity user copy Caleb Sander Mateos
2026-01-06 13:34   ` Ming Lei
2026-01-06 18:20     ` Caleb Sander Mateos
2026-01-07  0:28       ` Ming Lei
2026-01-08  1:50         ` Caleb Sander Mateos
2026-01-08  2:11           ` Ming Lei
2026-01-06 13:46   ` Ming Lei
2026-01-06  0:57 ` [PATCH v3 10/19] ublk: support UBLK_F_INTEGRITY Caleb Sander Mateos
2026-01-06 13:36   ` Ming Lei
2026-01-06  0:57 ` [PATCH v3 11/19] ublk: optimize ublk_user_copy() on daemon task Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 12/19] selftests: ublk: display UBLK_F_INTEGRITY support Caleb Sander Mateos
2026-01-06 13:38   ` Ming Lei
2026-01-06  0:57 ` [PATCH v3 13/19] selftests: ublk: add utility to get block device metadata size Caleb Sander Mateos
2026-01-06 13:50   ` Ming Lei
2026-01-06 17:18     ` Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 14/19] selftests: ublk: add kublk support for integrity params Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 15/19] selftests: ublk: implement integrity user copy in kublk Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 16/19] selftests: ublk: support non-O_DIRECT backing files Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 17/19] selftests: ublk: add integrity data support to loop target Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 18/19] selftests: ublk: add integrity params test Caleb Sander Mateos
2026-01-06  0:57 ` [PATCH v3 19/19] selftests: ublk: add end-to-end integrity test Caleb Sander Mateos
2026-01-06 14:10   ` Ming Lei
2026-01-06 17:15     ` Caleb Sander Mateos
2026-01-07  0:21       ` Ming Lei
2026-01-07  1:32         ` Caleb Sander Mateos
2026-01-07  1:49           ` Ming Lei

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aV2lhCLzISL0J-vH@fedora \
    --to=ming.lei@redhat.com \
    --cc=axboe@kernel.dk \
    --cc=csander@purestorage.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=shuah@kernel.org \
    --cc=stazhang@purestorage.com \
    --cc=ushankar@purestorage.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.