Skip to content

Commit c81bfba

Browse files
author
Christoph Hellwig
committed
nvme: only setup block integrity if supported by the driver
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@lst.de> Reviewed-by: Keith Busch <keith.busch@intel.com>
1 parent d3d5b87 commit c81bfba

File tree

3 files changed

+33
-19
lines changed

3 files changed

+33
-19
lines changed

drivers/nvme/host/core.c

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,29 @@ static int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo)
925925
}
926926

927927
#ifdef CONFIG_BLK_DEV_INTEGRITY
928+
static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
929+
u16 bs)
930+
{
931+
struct nvme_ns *ns = disk->private_data;
932+
u16 old_ms = ns->ms;
933+
u8 pi_type = 0;
934+
935+
ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);
936+
ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
937+
938+
/* PI implementation requires metadata equal t10 pi tuple size */
939+
if (ns->ms == sizeof(struct t10_pi_tuple))
940+
pi_type = id->dps & NVME_NS_DPS_PI_MASK;
941+
942+
if (blk_get_integrity(disk) &&
943+
(ns->pi_type != pi_type || ns->ms != old_ms ||
944+
bs != queue_logical_block_size(disk->queue) ||
945+
(ns->ms && ns->ext)))
946+
blk_integrity_unregister(disk);
947+
948+
ns->pi_type = pi_type;
949+
}
950+
928951
static void nvme_init_integrity(struct nvme_ns *ns)
929952
{
930953
struct blk_integrity integrity;
@@ -951,6 +974,10 @@ static void nvme_init_integrity(struct nvme_ns *ns)
951974
blk_queue_max_integrity_segments(ns->queue, 1);
952975
}
953976
#else
977+
static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
978+
u16 bs)
979+
{
980+
}
954981
static void nvme_init_integrity(struct nvme_ns *ns)
955982
{
956983
}
@@ -997,37 +1024,22 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
9971024
static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
9981025
{
9991026
struct nvme_ns *ns = disk->private_data;
1000-
u8 lbaf, pi_type;
1001-
u16 old_ms;
1002-
unsigned short bs;
1003-
1004-
old_ms = ns->ms;
1005-
lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
1006-
ns->lba_shift = id->lbaf[lbaf].ds;
1007-
ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
1008-
ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
1027+
u16 bs;
10091028

10101029
/*
10111030
* If identify namespace failed, use default 512 byte block size so
10121031
* block layer can use before failing read/write for 0 capacity.
10131032
*/
1033+
ns->lba_shift = id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ds;
10141034
if (ns->lba_shift == 0)
10151035
ns->lba_shift = 9;
10161036
bs = 1 << ns->lba_shift;
1017-
/* XXX: PI implementation requires metadata equal t10 pi tuple size */
1018-
pi_type = ns->ms == sizeof(struct t10_pi_tuple) ?
1019-
id->dps & NVME_NS_DPS_PI_MASK : 0;
10201037

10211038
blk_mq_freeze_queue(disk->queue);
1022-
if (blk_get_integrity(disk) && (ns->pi_type != pi_type ||
1023-
ns->ms != old_ms ||
1024-
bs != queue_logical_block_size(disk->queue) ||
1025-
(ns->ms && ns->ext)))
1026-
blk_integrity_unregister(disk);
10271039

1028-
ns->pi_type = pi_type;
1040+
if (ns->ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)
1041+
nvme_prep_integrity(disk, id, bs);
10291042
blk_queue_logical_block_size(ns->queue, bs);
1030-
10311043
if (ns->ms && !blk_get_integrity(disk) && !ns->ext)
10321044
nvme_init_integrity(ns);
10331045
if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk))

drivers/nvme/host/nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ struct nvme_ctrl_ops {
210210
struct module *module;
211211
unsigned int flags;
212212
#define NVME_F_FABRICS (1 << 0)
213+
#define NVME_F_METADATA_SUPPORTED (1 << 1)
213214
int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val);
214215
int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val);
215216
int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);

drivers/nvme/host/pci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,6 +2047,7 @@ static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl)
20472047
static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
20482048
.name = "pcie",
20492049
.module = THIS_MODULE,
2050+
.flags = NVME_F_METADATA_SUPPORTED,
20502051
.reg_read32 = nvme_pci_reg_read32,
20512052
.reg_write32 = nvme_pci_reg_write32,
20522053
.reg_read64 = nvme_pci_reg_read64,

0 commit comments

Comments
 (0)