]> www.infradead.org Git - nvme.git/commitdiff
nvme: implement ->get_unique_id
authorChristoph Hellwig <hch@lst.de>
Fri, 5 Jul 2024 16:46:26 +0000 (18:46 +0200)
committerKeith Busch <kbusch@kernel.org>
Mon, 8 Jul 2024 17:25:39 +0000 (10:25 -0700)
Implement the get_unique_id method to allow pNFS SCSI layout access to
NVMe namespaces.

This is the server side implementation of RFC 9561 "Using the Parallel
NFS (pNFS) SCSI Layout to Access Non-Volatile Memory Express (NVMe)
Storage Devices".

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h

index 20e7505852cea69c134ea90aecc77f926c7ac407..bfea6cccbc0ab3c2fc56561c007f6e121add6488 100644 (file)
@@ -2285,6 +2285,32 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
        return ret;
 }
 
+int nvme_ns_get_unique_id(struct nvme_ns *ns, u8 id[16],
+               enum blk_unique_id type)
+{
+       struct nvme_ns_ids *ids = &ns->head->ids;
+
+       if (type != BLK_UID_EUI64)
+               return -EINVAL;
+
+       if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) {
+               memcpy(id, &ids->nguid, sizeof(ids->nguid));
+               return sizeof(ids->nguid);
+       }
+       if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) {
+               memcpy(id, &ids->eui64, sizeof(ids->eui64));
+               return sizeof(ids->eui64);
+       }
+
+       return -EINVAL;
+}
+
+static int nvme_get_unique_id(struct gendisk *disk, u8 id[16],
+               enum blk_unique_id type)
+{
+       return nvme_ns_get_unique_id(disk->private_data, id, type);
+}
+
 #ifdef CONFIG_BLK_SED_OPAL
 static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len,
                bool send)
@@ -2340,6 +2366,7 @@ const struct block_device_operations nvme_bdev_ops = {
        .open           = nvme_open,
        .release        = nvme_release,
        .getgeo         = nvme_getgeo,
+       .get_unique_id  = nvme_get_unique_id,
        .report_zones   = nvme_report_zones,
        .pr_ops         = &nvme_pr_ops,
 };
index d8f3c1fb2ce5441eca923b46ee9355eb89ec1357..91d9eb3c22eff264101fc51d7d22b2a676e7cc37 100644 (file)
@@ -488,6 +488,21 @@ static void nvme_ns_head_release(struct gendisk *disk)
        nvme_put_ns_head(disk->private_data);
 }
 
+static int nvme_ns_head_get_unique_id(struct gendisk *disk, u8 id[16],
+               enum blk_unique_id type)
+{
+       struct nvme_ns_head *head = disk->private_data;
+       struct nvme_ns *ns;
+       int srcu_idx, ret = -EWOULDBLOCK;
+
+       srcu_idx = srcu_read_lock(&head->srcu);
+       ns = nvme_find_path(head);
+       if (ns)
+               ret = nvme_ns_get_unique_id(ns, id, type);
+       srcu_read_unlock(&head->srcu, srcu_idx);
+       return ret;
+}
+
 #ifdef CONFIG_BLK_DEV_ZONED
 static int nvme_ns_head_report_zones(struct gendisk *disk, sector_t sector,
                unsigned int nr_zones, report_zones_cb cb, void *data)
@@ -515,6 +530,7 @@ const struct block_device_operations nvme_ns_head_ops = {
        .ioctl          = nvme_ns_head_ioctl,
        .compat_ioctl   = blkdev_compat_ptr_ioctl,
        .getgeo         = nvme_getgeo,
+       .get_unique_id  = nvme_ns_head_get_unique_id,
        .report_zones   = nvme_ns_head_report_zones,
        .pr_ops         = &nvme_pr_ops,
 };
index b512012b704491b242e8b275bcc8109a7546a0fc..9ac587e64166366ea96c26e88e2ada843467b68b 100644 (file)
@@ -1059,6 +1059,9 @@ static inline bool nvme_disk_is_ns_head(struct gendisk *disk)
 }
 #endif /* CONFIG_NVME_MULTIPATH */
 
+int nvme_ns_get_unique_id(struct nvme_ns *ns, u8 id[16],
+               enum blk_unique_id type);
+
 struct nvme_zone_info {
        u64 zone_size;
        unsigned int max_open_zones;