1d4e7048c9
Signed-off-by: Peter Jones <pjones@redhat.com>
189 lines
4.9 KiB
Diff
189 lines
4.9 KiB
Diff
From 47b2772a8e419ebadcf54182bfbd6170f7ab24f1 Mon Sep 17 00:00:00 2001
|
|
From: Peter Jones <pjones@redhat.com>
|
|
Date: Mon, 14 Apr 2014 17:19:57 -0400
|
|
Subject: [PATCH 04/22] Make nvme work with "-e 3".
|
|
|
|
This will force a long-form NVME device path.
|
|
|
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
---
|
|
src/include/disk.h | 2 +-
|
|
src/include/scsi_ioctls.h | 1 +
|
|
src/lib/disk.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
|
src/lib/efi.c | 29 +++++++++++++++++++++++++++--
|
|
src/lib/scsi_ioctls.c | 7 +++++++
|
|
5 files changed, 81 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/include/disk.h b/src/include/disk.h
|
|
index 720248c..3b3370d 100644
|
|
--- a/src/include/disk.h
|
|
+++ b/src/include/disk.h
|
|
@@ -65,7 +65,7 @@ enum _bus_type {bus_type_unknown, isa, pci};
|
|
enum _interface_type {interface_type_unknown,
|
|
ata, atapi, scsi, usb,
|
|
i1394, fibre, i2o, md,
|
|
- virtblk};
|
|
+ virtblk, nvme};
|
|
|
|
|
|
unsigned int lcm(unsigned int x, unsigned int y);
|
|
diff --git a/src/include/scsi_ioctls.h b/src/include/scsi_ioctls.h
|
|
index ba4c8bb..995cbbd 100644
|
|
--- a/src/include/scsi_ioctls.h
|
|
+++ b/src/include/scsi_ioctls.h
|
|
@@ -38,6 +38,7 @@ typedef struct scsi_idlun {
|
|
} Scsi_Idlun;
|
|
|
|
|
|
+int get_nvme_ns_id(int fd, uint32_t *ns_id);
|
|
inline int get_scsi_idlun(int fd, Scsi_Idlun *idlun);
|
|
int get_scsi_pci(int fd, char *slot_name, size_t size);
|
|
int idlun_to_components (Scsi_Idlun *idlun,
|
|
diff --git a/src/lib/disk.c b/src/lib/disk.c
|
|
index 636b509..ad95fd4 100644
|
|
--- a/src/lib/disk.c
|
|
+++ b/src/lib/disk.c
|
|
@@ -75,6 +75,45 @@ get_virtblk_major(void)
|
|
return cached;
|
|
}
|
|
|
|
+static int
|
|
+get_nvme_major(void)
|
|
+{
|
|
+ static int cached;
|
|
+ FILE *f;
|
|
+ char line[256];
|
|
+
|
|
+ if (cached != 0) {
|
|
+ return cached;
|
|
+ }
|
|
+
|
|
+ cached = -1;
|
|
+ f = fopen("/proc/devices", "r");
|
|
+ if (f == NULL) {
|
|
+ fprintf(stderr, "%s: opening /proc/devices: %s\n", __func__,
|
|
+ strerror(errno));
|
|
+ return cached;
|
|
+ }
|
|
+ while (fgets(line, sizeof line, f) != NULL) {
|
|
+ size_t len = strlen(line);
|
|
+ int major, scanned;
|
|
+
|
|
+ if (len == 0 || line[len - 1] != '\n') {
|
|
+ break;
|
|
+ }
|
|
+ if (sscanf(line, "%d %n", &major, &scanned) == 1 &&
|
|
+ strcmp(line + scanned, "nvme\n") == 0) {
|
|
+ cached = major;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ fclose(f);
|
|
+ if (cached == -1) {
|
|
+ fprintf(stderr, "%s: nvme driver unavailable\n",
|
|
+ __func__);
|
|
+ }
|
|
+ return cached;
|
|
+}
|
|
+
|
|
int
|
|
disk_info_from_fd(int fd, struct disk_info *info)
|
|
{
|
|
@@ -165,6 +204,12 @@ disk_info_from_fd(int fd, struct disk_info *info)
|
|
return 0;
|
|
}
|
|
|
|
+ if (get_nvme_major() >= 0 &&
|
|
+ (uint64_t)get_nvme_major() == info->major) {
|
|
+ info->interface_type = nvme;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (get_virtblk_major() >= 0 &&
|
|
(uint64_t)get_virtblk_major() == info->major) {
|
|
info->interface_type = virtblk;
|
|
diff --git a/src/lib/efi.c b/src/lib/efi.c
|
|
index 078bbc5..7b5e7fd 100644
|
|
--- a/src/lib/efi.c
|
|
+++ b/src/lib/efi.c
|
|
@@ -352,6 +352,20 @@ make_pci_device_path(uint8_t bus, uint8_t device, uint8_t function,
|
|
}
|
|
|
|
static ssize_t
|
|
+make_nvme_device_path(uint32_t ns_id, uint8_t *buf, size_t size)
|
|
+{
|
|
+ NVME_DEVICE_PATH p;
|
|
+ memset(&p, 0, sizeof(p));
|
|
+ p.type = 3;
|
|
+ p.subtype = 23;
|
|
+ p.length = sizeof(p);
|
|
+ p.namespace_id = ns_id;
|
|
+ if (size >= p.length)
|
|
+ memcpy(buf, &p, p.length);
|
|
+ return p.length;
|
|
+}
|
|
+
|
|
+static ssize_t
|
|
make_scsi_device_path(uint16_t id, uint16_t lun, uint8_t *buf, size_t size)
|
|
{
|
|
SCSI_DEVICE_PATH p;
|
|
@@ -420,13 +434,18 @@ make_edd30_device_path(int fd, uint8_t *buf, size_t size)
|
|
int rc=0, interface_type;
|
|
unsigned char bus=0, device=0, function=0;
|
|
Scsi_Idlun idlun;
|
|
+ uint32_t ns_id;
|
|
unsigned char host=0, channel=0, id=0, lun=0;
|
|
size_t needed;
|
|
off_t buf_offset = 0;
|
|
|
|
rc = disk_get_pci(fd, &interface_type, &bus, &device, &function);
|
|
if (rc) return 0;
|
|
- if (interface_type != virtblk) {
|
|
+ if (interface_type == nvme) {
|
|
+ rc = get_nvme_ns_id(fd, &ns_id);
|
|
+ if (rc)
|
|
+ return 0;
|
|
+ } else if (interface_type != virtblk) {
|
|
memset(&idlun, 0, sizeof(idlun));
|
|
rc = get_scsi_idlun(fd, &idlun);
|
|
if (rc) return 0;
|
|
@@ -444,7 +463,13 @@ make_edd30_device_path(int fd, uint8_t *buf, size_t size)
|
|
return needed;
|
|
buf_offset += needed;
|
|
|
|
- if (interface_type != virtblk) {
|
|
+ if (interface_type == nvme) {
|
|
+ needed = make_nvme_device_path(ns_id, buf + buf_offset,
|
|
+ size == 0 ? 0 : size - buf_offset);
|
|
+ if (needed < 0)
|
|
+ return needed;
|
|
+ buf_offset += needed;
|
|
+ } else if (interface_type != virtblk) {
|
|
needed = make_scsi_device_path(id, lun, buf + buf_offset,
|
|
size == 0 ? 0 : size - buf_offset);
|
|
if (needed < 0)
|
|
diff --git a/src/lib/scsi_ioctls.c b/src/lib/scsi_ioctls.c
|
|
index 615b48f..e013a6f 100644
|
|
--- a/src/lib/scsi_ioctls.c
|
|
+++ b/src/lib/scsi_ioctls.c
|
|
@@ -24,9 +24,16 @@
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
+#include <linux/nvme.h>
|
|
#include "scsi_ioctls.h"
|
|
|
|
int
|
|
+get_nvme_ns_id(int fd, uint32_t *ns_id)
|
|
+{
|
|
+ return ioctl(fd, NVME_IOCTL_ID, &ns_id);
|
|
+}
|
|
+
|
|
+int
|
|
idlun_to_components (Scsi_Idlun *idlun,
|
|
unsigned char *host,
|
|
unsigned char *channel,
|
|
--
|
|
1.9.3
|
|
|