[PATCH 3/3] nvme: only setup block integrity if supported by the driver
Christoph Hellwig
hch at infradead.org
Thu May 25 01:33:08 PDT 2017
Any chance to get a review for this one? Without it we'll reliably
crash the kernel if a fabrics target advertises metadata support.
On Sat, May 20, 2017 at 03:14:45PM +0200, Christoph Hellwig wrote:
> Currently only the PCIe driver supports metadata, so we should not claim
> integrity support for the other drivers. This prevents nasty crashes
> with targets that advertise metadata support on fabrics.
>
> Also use the opportunity to factor out some code into a separate helper
> that isn't even compiled if CONFIG_BLK_DEV_INTEGRITY is disabled.
>
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
> drivers/nvme/host/core.c | 50 ++++++++++++++++++++++++++++++------------------
> drivers/nvme/host/nvme.h | 1 +
> drivers/nvme/host/pci.c | 1 +
> 3 files changed, 33 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index 79b78bd67b07..f6dd4fed56a4 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -925,6 +925,29 @@ static int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo)
> }
>
> #ifdef CONFIG_BLK_DEV_INTEGRITY
> +static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
> + u16 bs)
> +{
> + struct nvme_ns *ns = disk->private_data;
> + u16 old_ms = ns->ms;
> + u8 pi_type = 0;
> +
> + ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);
> + ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
> +
> + /* PI implementation requires metadata equal t10 pi tuple size */
> + if (ns->ms == sizeof(struct t10_pi_tuple))
> + pi_type = id->dps & NVME_NS_DPS_PI_MASK;
> +
> + if (blk_get_integrity(disk) &&
> + (ns->pi_type != pi_type || ns->ms != old_ms ||
> + bs != queue_logical_block_size(disk->queue) ||
> + (ns->ms && ns->ext)))
> + blk_integrity_unregister(disk);
> +
> + ns->pi_type = pi_type;
> +}
> +
> static void nvme_init_integrity(struct nvme_ns *ns)
> {
> struct blk_integrity integrity;
> @@ -951,6 +974,10 @@ static void nvme_init_integrity(struct nvme_ns *ns)
> blk_queue_max_integrity_segments(ns->queue, 1);
> }
> #else
> +static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
> + u16 bs)
> +{
> +}
> static void nvme_init_integrity(struct nvme_ns *ns)
> {
> }
> @@ -997,37 +1024,22 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
> static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
> {
> struct nvme_ns *ns = disk->private_data;
> - u8 lbaf, pi_type;
> - u16 old_ms;
> - unsigned short bs;
> -
> - old_ms = ns->ms;
> - lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
> - ns->lba_shift = id->lbaf[lbaf].ds;
> - ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
> - ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
> + u16 bs;
>
> /*
> * If identify namespace failed, use default 512 byte block size so
> * block layer can use before failing read/write for 0 capacity.
> */
> + ns->lba_shift = id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ds;
> if (ns->lba_shift == 0)
> ns->lba_shift = 9;
> bs = 1 << ns->lba_shift;
> - /* XXX: PI implementation requires metadata equal t10 pi tuple size */
> - pi_type = ns->ms == sizeof(struct t10_pi_tuple) ?
> - id->dps & NVME_NS_DPS_PI_MASK : 0;
>
> blk_mq_freeze_queue(disk->queue);
> - if (blk_get_integrity(disk) && (ns->pi_type != pi_type ||
> - ns->ms != old_ms ||
> - bs != queue_logical_block_size(disk->queue) ||
> - (ns->ms && ns->ext)))
> - blk_integrity_unregister(disk);
>
> - ns->pi_type = pi_type;
> + if (ns->ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)
> + nvme_prep_integrity(disk, id, bs);
> blk_queue_logical_block_size(ns->queue, bs);
> -
> if (ns->ms && !blk_get_integrity(disk) && !ns->ext)
> nvme_init_integrity(ns);
> if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk))
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index 7c4b0f6636c5..9d6a070d4391 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -210,6 +210,7 @@ struct nvme_ctrl_ops {
> struct module *module;
> unsigned int flags;
> #define NVME_F_FABRICS (1 << 0)
> +#define NVME_F_METADATA_SUPPORTED (1 << 1)
> int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val);
> int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val);
> int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index a150b2dd7851..283efc2e8921 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -2041,6 +2041,7 @@ static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl)
> static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
> .name = "pcie",
> .module = THIS_MODULE,
> + .flags = NVME_F_METADATA_SUPPORTED,
> .reg_read32 = nvme_pci_reg_read32,
> .reg_write32 = nvme_pci_reg_write32,
> .reg_read64 = nvme_pci_reg_read64,
> --
> 2.11.0
>
>
> _______________________________________________
> Linux-nvme mailing list
> Linux-nvme at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-nvme
---end quoted text---
More information about the Linux-nvme
mailing list