[LTP] [PATCH v3] testcases/kernel/device-drivers/nvme: Add NVMe device discovery test

Daniel Wagner dwagner@suse.de
Tue May 5 10:45:16 CEST 2026


Adding Shin'ichiro

On 5/5/26 5:46 AM, Sebastian Chlad wrote:
> Hi Priyama,
> 
> Sorry for top-posting, but I have a broader question here.
> 
> First of all, thanks for working on this and for looking into NVMe coverage.
> 
> Before going further, could you please explain the intended LTP-specific 
> value of
> this test? blktests already has a dedicated NVMe test group with much 
> broader
> coverage, including controller/namespace discovery, NVMe commands, 
> fabrics, etc.:
> 
> https://github.com/linux-blktests/blktests/tree/master/tests/nvme 
> <https://github.com/linux-blktests/blktests/tree/master/tests/nvme>
> 
> So I think we should be careful not to duplicate coverage unless there 
> is a clear
> reason for having a small LTP-level smoke test as well. Maybe your 
> intention is
> different? Could you please clarify?
> 
> Cheers,
> Sebastian
> 
> On Thu, 30 Apr 2026 at 07:10, <priyama2@linux.ibm.com 
> <mailto:priyama2@linux.ibm.com>> wrote:
> 
>     From: priyama2 <priyama2@linux.ibm.com <mailto:priyama2@linux.ibm.com>>
> 
>     This test fills a gap in NVMe test coverage by validating basic device
>     enumeration and driver binding, which are fundamental prerequisites for
>     any NVMe functionality testing.
> 
>     The test verifies:
>     - Detection of NVMe controllers in /dev
>     - Enumeration of namespaces for detected controllers
>     - PCI enumeration (class code 0x010802)
>     - NVMe driver binding
> 
>     Changes in v3:
>     - Fix subject prefix to match directory path
>     - Update copyright year to 2026
>     - Add nvme to SUBDIRS in testcases/kernel/device-drivers/Makefile
>     - Reset static variables at start of run() for -i support
>     - Remove .needs_root (all operations are world-readable)
>     - Use SAFE_FOPEN/SAFE_FCLOSE for PCI class file access
>     - Use SAFE_READLINK for driver symlink reading
>     - Add .gitignore entry for nvme01 binary
>     - Add runtest/device-drivers entry for nvme01
>     - Fix author field to use priyama2
> 
>     Changes in v2:
>     - Use LTP buildsystem instead of standalone Makefile
>     - Remove README file (use doc comments instead)
>     - Add proper LTP documentation comment format
>     - Use SAFE_OPENDIR() and SAFE_CLOSEDIR() macros
>     - Remove obvious and redundant comments
>     - Code cleanup and style improvements
> 
>     Signed-off-by: priyama2 <priyama2@linux.ibm.com
>     <mailto:priyama2@linux.ibm.com>>
>     ---
>       runtest/device-drivers                        |   1 +
>       testcases/kernel/device-drivers/Makefile      |   1 +
>       .../kernel/device-drivers/nvme/.gitignore     |   1 +
>       testcases/kernel/device-drivers/nvme/Makefile |   7 +
>       testcases/kernel/device-drivers/nvme/nvme01.c | 205 ++++++++++++++++++
>       5 files changed, 215 insertions(+)
>       create mode 100644 runtest/device-drivers
>       create mode 100644 testcases/kernel/device-drivers/nvme/.gitignore
>       create mode 100644 testcases/kernel/device-drivers/nvme/Makefile
>       create mode 100644 testcases/kernel/device-drivers/nvme/nvme01.c
> 
>     diff --git a/runtest/device-drivers b/runtest/device-drivers
>     new file mode 100644
>     index 000000000..a7295584e
>     --- /dev/null
>     +++ b/runtest/device-drivers
>     @@ -0,0 +1 @@
>     +nvme01 nvme01
>     diff --git a/testcases/kernel/device-drivers/Makefile b/testcases/
>     kernel/device-drivers/Makefile
>     index 229a50683..664f4cd18 100644
>     --- a/testcases/kernel/device-drivers/Makefile
>     +++ b/testcases/kernel/device-drivers/Makefile
>     @@ -9,6 +9,7 @@ SUBDIRS         := acpi \
>                         block \
>                         cpufreq \
>                         locking \
>     +                  nvme \
>                         pci \
>                         rcu \
>                         rtc \
>     diff --git a/testcases/kernel/device-drivers/nvme/.gitignore b/
>     testcases/kernel/device-drivers/nvme/.gitignore
>     new file mode 100644
>     index 000000000..c60bc210c
>     --- /dev/null
>     +++ b/testcases/kernel/device-drivers/nvme/.gitignore
>     @@ -0,0 +1 @@
>     +nvme01
>     diff --git a/testcases/kernel/device-drivers/nvme/Makefile b/
>     testcases/kernel/device-drivers/nvme/Makefile
>     new file mode 100644
>     index 000000000..d47e99e6a
>     --- /dev/null
>     +++ b/testcases/kernel/device-drivers/nvme/Makefile
>     @@ -0,0 +1,7 @@
>     +# SPDX-License-Identifier: GPL-2.0-or-later
>     +# Copyright (c) 2024 IBM Corporation
>     +
>     +top_srcdir     ?= ../../../..
>     +
>     +include $(top_srcdir)/include/mk/env_pre.mk <http://env_pre.mk>
>     +include $(top_srcdir)/include/mk/generic_trunk_target.mk <http://
>     generic_trunk_target.mk>
>     diff --git a/testcases/kernel/device-drivers/nvme/nvme01.c b/
>     testcases/kernel/device-drivers/nvme/nvme01.c
>     new file mode 100644
>     index 000000000..3c3cb92ce
>     --- /dev/null
>     +++ b/testcases/kernel/device-drivers/nvme/nvme01.c
>     @@ -0,0 +1,205 @@
>     +// SPDX-License-Identifier: GPL-2.0-or-later
>     +/*
>     + * Copyright (c) 2026 IBM Corporation
>     + * Author: priyama2 <priyama2@linux.ibm.com
>     <mailto:priyama2@linux.ibm.com>>
>     + */
>     +
>     +/* * [Description]
>     + *
>     + * Verify NVMe device discovery and identification.
>     + *
>     + * This test fills a gap in NVMe test coverage by validating basic
>     device
>     + * enumeration and driver binding, which are fundamental
>     prerequisites for
>     + * any NVMe functionality testing.
>     + *
>     + * - Detect NVMe controllers in /dev
>     + * - Enumerate namespaces for detected controllers
>     + * - Verify PCI enumeration (class code 0x010802)
>     + * - Check NVMe driver binding
>     + */
>     +
>     +#define _GNU_SOURCE
>     +#include <stdio.h>
>     +#include <stdlib.h>
>     +#include <string.h>
>     +#include <unistd.h>
>     +#include <fcntl.h>
>     +#include <sys/types.h>
>     +#include <sys/stat.h>
>     +#include <dirent.h>
>     +#include <errno.h>
>     +
>     +#include "tst_test.h"
>     +#include "tst_safe_stdio.h"
>     +
>     +#define NVME_DEV_PATH "/dev"
>     +#define NVME_SYS_PATH "/sys/class/nvme"
>     +#define PCI_DEVICES_PATH "/sys/bus/pci/devices"
>     +
>     +static int nvme_device_found;
>     +static char nvme_dev_name[256];
>     +
>     +static void test_detect_nvme_controllers(void)
>     +{
>     +       DIR *dir;
>     +       struct dirent *entry;
>     +       int found = 0;
>     +
>     +       dir = SAFE_OPENDIR(NVME_DEV_PATH);
>     +
>     +       tst_res(TINFO, "Scanning for NVMe devices in %s",
>     NVME_DEV_PATH);
>     +
>     +       while ((entry = readdir(dir)) != NULL) {
>     +               if (strncmp(entry->d_name, "nvme", 4) == 0 &&
>     +                   strlen(entry->d_name) == 5) {
>     +                       tst_res(TINFO, "Found NVMe controller: %s",
>     entry->d_name);
>     +                       strncpy(nvme_dev_name, entry->d_name,
>     sizeof(nvme_dev_name) - 1);
>     +                       found = 1;
>     +                       nvme_device_found = 1;
>     +               }
>     +       }
>     +
>     +       SAFE_CLOSEDIR(dir);
>     +
>     +       if (found)
>     +               tst_res(TPASS, "NVMe controller(s) detected
>     successfully");
>     +       else
>     +               tst_res(TCONF, "No NVMe controllers found in system");
>     +}
>     +
>     +static void test_enumerate_namespaces(void)
>     +{
>     +       DIR *dir;
>     +       struct dirent *entry;
>     +       int ns_count = 0;
>     +       char search_pattern[32];
>     +
>     +       if (!nvme_device_found) {
>     +               tst_res(TCONF, "No NVMe device found, skipping
>     namespace enumeration");
>     +               return;
>     +       }
>     +
>     +       snprintf(search_pattern, sizeof(search_pattern), "%sn",
>     nvme_dev_name);
>     +
>     +       dir = SAFE_OPENDIR(NVME_DEV_PATH);
>     +
>     +       tst_res(TINFO, "Enumerating namespaces for %s", nvme_dev_name);
>     +
>     +       while ((entry = readdir(dir)) != NULL) {
>     +               if (strncmp(entry->d_name, search_pattern,
>     strlen(search_pattern)) == 0) {
>     +                       tst_res(TINFO, "Found namespace: %s", entry-
>      >d_name);
>     +                       ns_count++;
>     +               }
>     +       }
>     +
>     +       SAFE_CLOSEDIR(dir);
>     +
>     +       if (ns_count > 0)
>     +               tst_res(TPASS, "Enumerated %d namespace(s)
>     successfully", ns_count);
>     +       else
>     +               tst_res(TPASS, "No namespaces found for %s (device
>     may not have namespaces configured)", nvme_dev_name);
>     +}
>     +
>     +static void test_verify_pci_enumeration(void)
>     +{
>     +       DIR *dir;
>     +       struct dirent *entry;
>     +       int found = 0;
>     +       char class_path[512];
>     +       FILE *fp;
>     +       char class_id[16];
>     +
>     +       if (!nvme_device_found) {
>     +               tst_res(TCONF, "No NVMe device found, skipping PCI
>     enumeration check");
>     +               return;
>     +       }
>     +
>     +       dir = SAFE_OPENDIR(PCI_DEVICES_PATH);
>     +
>     +       tst_res(TINFO, "Checking PCI enumeration for NVMe devices");
>     +
>     +       while ((entry = readdir(dir)) != NULL) {
>     +               if (entry->d_name[0] == '.')
>     +                       continue;
>     +
>     +               snprintf(class_path, sizeof(class_path), "%s/%s/class",
>     +                        PCI_DEVICES_PATH, entry->d_name);
>     +
>     +               fp = SAFE_FOPEN(class_path, "r");
>     +
>     +               if (fgets(class_id, sizeof(class_id), fp)) {
>     +                       if (strncmp(class_id, "0x010802", 8) == 0) {
>     +                               tst_res(TINFO, "Found NVMe PCI
>     device: %s (class: %s)",
>     +                                       entry->d_name, class_id);
>     +                               found = 1;
>     +                       }
>     +               }
>     +               SAFE_FCLOSE(fp);
>     +       }
>     +
>     +       SAFE_CLOSEDIR(dir);
>     +
>     +       if (found)
>     +               tst_res(TPASS, "NVMe device properly enumerated on
>     PCI bus");
>     +       else
>     +               tst_res(TFAIL, "NVMe device not found on PCI bus");
>     +}
>     +
>     +static void test_check_driver_binding(void)
>     +{
>     +       char driver_path[512];
>     +       char driver_link[512];
>     +
>     +       if (!nvme_device_found) {
>     +               tst_res(TCONF, "No NVMe device found, skipping
>     driver binding check");
>     +               return;
>     +       }
>     +
>     +       snprintf(driver_path, sizeof(driver_path), "%s/%s/device/
>     driver",
>     +                NVME_SYS_PATH, nvme_dev_name);
>     +
>     +       SAFE_READLINK(driver_path, driver_link, sizeof(driver_link));
>     +
>     +       tst_res(TINFO, "Driver binding: %s", driver_link);
>     +
>     +       if (strstr(driver_link, "nvme") != NULL)
>     +               tst_res(TPASS, "NVMe driver properly bound to device");
>     +       else
>     +               tst_res(TFAIL, "Unexpected driver bound to NVMe
>     device: %s", driver_link);
>     +}
>     +
>     +static void setup(void)
>     +{
>     +       if (access("/sys/module/nvme", F_OK) != 0)
>     +               tst_brk(TCONF, "NVMe kernel module not loaded");
>     +
>     +       tst_res(TINFO, "NVMe Device Discovery & Identification Test");
>     +}
>     +
>     +static void run(unsigned int n)
>     +{
>     +       /* Reset state for each iteration */
>     +       nvme_device_found = 0;
>     +       memset(nvme_dev_name, 0, sizeof(nvme_dev_name));
>     +
>     +       switch (n) {
>     +       case 0:
>     +               test_detect_nvme_controllers();
>     +               break;
>     +       case 1:
>     +               test_enumerate_namespaces();
>     +               break;
>     +       case 2:
>     +               test_verify_pci_enumeration();
>     +               break;
>     +       case 3:
>     +               test_check_driver_binding();
>     +               break;
>     +       }
>     +}
>     +
>     +static struct tst_test test = {
>     +       .test = run,
>     +       .tcnt = 4,
>     +       .setup = setup,
>     +};
>     -- 
>     2.52.0
> 
> 
>     -- 
>     Mailing list info: https://lists.linux.it/listinfo/ltp <https://
>     lists.linux.it/listinfo/ltp>
> 



More information about the ltp mailing list