diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c67ca39077..105d8f737c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,26 +1,237 @@ -# Contributing to the NVM-e CLI +# Contributing to nvme-cli and libnvme Here you will find instructions on how to contribute to the NVM-Express command -line interface. +line interface and the libnvme library. Contributions and new ideas are most welcome! -**NOTE: If you do decide to implement code changes and contribute them, -please make sure you agree your contribution can be made available -under the [GPLv2-style License used for the NVMe CLI](https://github.com/linux-nvme/nvme-cli/blob/master/LICENSE). -(SPDX-License-Identifier: GPL-2.0-or-later)** +This repository contains two components with different licenses: -Because there are a few files licensed under GPL-2.0-only, the whole -project is tagged as GPL-2.0-only and not as GPL-2.0-or-later. +| Component | License | SPDX identifier | +|-----------|---------|-----------------| +| nvme-cli (CLI and plugins) | GNU General Public License v2 or later | `GPL-2.0-or-later` | +| libnvme (library) | GNU Lesser General Public License v2.1 or later | `LGPL-2.1-or-later` | -### Code Contributions +When contributing, use the appropriate SPDX identifier for the component you +are modifying. New files under `libnvme/` should carry `LGPL-2.1-or-later`; +new files in the CLI or plugins should carry `GPL-2.0-or-later`. -Please feel free to use the github forums to ask for comments & questions on -your code before submitting a pull request. The NVMe CLI project uses the -common *fork and merge* workflow used by most GitHub-hosted projects. +## API naming conventions -#### Commit conventions +### Spec-mirroring definitions (`nvme_` / `nvmf_`) + +Types, structs, and enums that directly mirror the NVMe specifications use the +short `nvme_` (base spec) and `nvmf_` (NVMe-oF spec) prefixes. These live in +`libnvme/src/nvme/types.h` and `libnvme/src/nvme/cmds.h` and reflect the +specification naming — they are data-layout definitions, not library API. + +### libnvme public API (`libnvme_` / `libnvmf_`) + +This is where the naming convention is enforced. libnvme is a shared library +with a stable public ABI, so every public symbol must carry the correct prefix +so that callers can immediately tell what they are working with. + +| Prefix | Scope | Examples | +|--------|-------|---------| +| `libnvme_` | Common NVMe (PCIe and NVMe-oF) | `libnvme_open()`, `libnvme_create_global_ctx()`, `libnvme_first_host()`, `libnvme_ctrl_identify()` | +| `libnvmf_` | NVMe-oF only | `libnvmf_connect_ctrl()`, `libnvmf_add_ctrl()`, `libnvmf_get_discovery_log()`, `libnvmf_trtype_str()` | + +The split is enforced by two separate linker version scripts: +`libnvme/src/libnvme.ld` exports all `libnvme_*` symbols and +`libnvme/src/libnvmf.ld` exports all `libnvmf_*` symbols. Both are passed to +the linker when building `libnvme.so`. + +When contributing new functions to libnvme, choose the prefix based on scope: +- Use `libnvme_` if the function applies to both PCIe and NVMe-oF controllers. +- Use `libnvmf_` if the function is specific to NVMe-oF (fabrics transport, + discovery, connect/disconnect). + +## Adding commands and plugins + +You may wish to add a new command or possibly an entirely new plug-in +for some special extension outside the spec. + +This project provides macros that help generate the code for you. If +you're interested in how that works, it is very similar to how trace +events are created by Linux kernel's 'ftrace' component. + +### Add a command to the existing built-in + +The first thing to do is define a new command entry in the command +list. This is declared in nvme-builtin.h. Simply append a new "ENTRY" into +the list. The ENTRY normally takes three arguments: the "name" of the +subcommand (this is what the user will type at the command line to invoke +your command), a short help description of what your command does, and the +name of the function callback that you're going to write. Additionally, +you can declare an alias name of the subcommand with a fourth argument, if +needed. + +After the ENTRY is defined, you need to implement the callback. It takes +four arguments: argc, argv, the command structure associated with the +callback, and the plug-in structure that contains that command. The +prototype looks like this: + + ```c + int f(int argc, char **argv, struct command *command, struct plugin *plugin); + ``` + +The argc and argv are adjusted from the command line arguments to start +after the sub-command. So if the command line is "nvme foo --option=bar", +the argc is 1 and argv starts at "--option". + +You can then define argument parsing for your sub-command's specific +options then do some command-specific action in your callback. + +### Add a new plugin + +The nvme-cli provides macros to make defining a new plug-in simpler. You +can certainly do all this by hand if you want, but it should be easier +to get going using the macros. To start, first create a header file +to define your plugin. This is where you will give your plugin a name, +description, and define all the sub-commands your plugin implements. + +The macros must appear in a specific order within the header file. The following +is a basic example on how to start this: + +File: foo-plugin.h +```c +#undef CMD_INC_FILE +#define CMD_INC_FILE plugins/foo/foo-plugin + +#if !defined(FOO) || defined(CMD_HEADER_MULTI_READ) +#define FOO + +#include "cmd.h" + +PLUGIN(NAME("foo", "Foo plugin"), + COMMAND_LIST( + ENTRY("bar", "foo bar", bar) + ENTRY("baz", "foo baz", baz) + ENTRY("qux", "foo qux", qux) + ) +); + +#endif + +#include "define_cmd.h" +``` + +In order to have the compiler generate the plugin through the xmacro +expansion, you need to include this header in your source file, with +a pre-defining macro directive to create the commands. + +To get started from the above example, we just need to define "CREATE_CMD" +and include the header: + +File: foo-plugin.c +```c +#include "nvme.h" + +#define CREATE_CMD +#include "foo-plugin.h" +``` + +After that, you just need to implement the functions you defined in each +ENTRY, then append the object file name to the meson.build "sources". + +### Updating the libnvme accessor functions + +libnvme exposes auto-generated getter/setter accessor functions for its +ABI-stable opaque structs. Two sets of accessors are maintained — one for +common NVMe structs and one for NVMe-oF-specific structs. The split exists so +that non-fabrics (e.g. embedded or PCIe-only) builds can exclude all fabrics +code entirely. + +| Meson target | Input header | Generated files | +|---|---|---| +| `update-common-accessors` | `libnvme/src/nvme/private.h` | `libnvme/src/nvme/accessors.{h,c}`, `libnvme/src/accessors.ld` | +| `update-fabrics-accessors` | `libnvme/src/nvme/private-fabrics.h` | `libnvme/src/nvme/accessors-fabrics.{h,c}`, `libnvme/src/accessors-fabrics.ld` | + +The generated `.h` and `.c` files are committed to the source tree and are +**not** regenerated during a normal build. + +#### When to regenerate + +Regeneration is needed whenever a `/*!generate-accessors*/` struct in +`private.h` or `private-fabrics.h` has a member added, removed, or renamed. + +#### How to regenerate + +To regenerate both sets at once: + +```shell +$ meson compile -C .build update-accessors +``` + +Or regenerate only one set: + +```shell +$ meson compile -C .build update-common-accessors +$ meson compile -C .build update-fabrics-accessors +``` + +The script atomically updates the `.h` and `.c` files when their content +changes. Commit the updated files afterward: + +```shell +$ git add libnvme/src/nvme/accessors.h libnvme/src/nvme/accessors.c +$ git add libnvme/src/nvme/accessors-fabrics.h libnvme/src/nvme/accessors-fabrics.c +$ git commit -m "libnvme: regenerate accessors following changes" +``` + +#### Maintaining the .ld version-script files + +The `.ld` files (`libnvme/src/accessors.ld` and +`libnvme/src/accessors-fabrics.ld`) are GNU linker version scripts that +control which accessor symbols are exported from the shared library and under +which ABI version label they were introduced (e.g. `LIBNVME_ACCESSORS_3`, +`LIBNVMF_ACCESSORS_3`). + +These files are **not** updated automatically, because each new symbol must be +placed in the correct version section by the maintainer. Adding a symbol to an +already-published version section would break binary compatibility for +existing users of the library. + +When the generator detects that the symbol list has drifted, it prints a +report like the following: + +``` +WARNING: accessors.ld needs manual attention. + + Symbols to ADD (new version section, e.g. LIBNVME_ACCESSORS_X_Y): + libnvme_ctrl_get_new_field + libnvme_ctrl_set_new_field +``` + +New symbols must be added to a **new** version section that chains the +previous one. For example, if the current latest section is +`LIBNVME_ACCESSORS_3`, add: + +``` +LIBNVME_ACCESSORS_4 { + global: + libnvme_ctrl_get_new_field; + libnvme_ctrl_set_new_field; +} LIBNVME_ACCESSORS_3; +``` + +Then commit the updated `.ld` file together with the regenerated source files. + +## Submitting changes + +There are two ways to send code changes to the project. The first one +is by sending the changes to linux-nvme@lists.infradead.org. The +second one is by posting a pull request on Github. In both cases +please follow the Linux contributions guidelines as documented in +[Submitting patches](https://docs.kernel.org/process/submitting-patches.html). + +That means the changes should be a clean series (no merges should be +present in a Github PR for example) and every commit should build. + +See also [How to create a pull request on GitHub](https://opensource.com/article/19/7/create-pull-request-github). + +### Commit conventions The project follows the Linux kernel mailing list workflow, thus commit messages should be structured like this: @@ -42,6 +253,39 @@ Show new contributors the project's commit guidelines Signed-off-by: John Doe ``` -### Bug Reports +### How to clean up your series before creating a PR + +This example here assumes the changes are in a branch called +fix-something, which branched away from master in the past. In the +meantime the upstream project has changed, hence the fix-something +branch is not based on the current HEAD. Before posting the PR, the +branch should be rebased on the current HEAD and retest everything. + +For example, rebasing can be done by the following steps + +```shell +# Update master branch +# upstream == https://github.com/linux-nvme/nvme-cli.git +$ git switch master +$ git fetch --all +$ git reset --hard upstream/master + +# Make sure all dependencies are up to date and make a sanity build +$ meson subprojects update +$ ninja -C .build + +# Go back to the fix-something branch +$ git switch fix-something + +# Rebase it to the current HEAD +$ git rebase master +[fixup all merge conflicts] +[retest] + +# Push your changes to Github and trigger a PR +$ git push -u origin fix-something +``` + +## Bug Reports Bugs for the NVM Library project are tracked in our [GitHub Issues Database](https://github.com/linux-nvme/nvme-cli/issues). diff --git a/README.md b/README.md index bf1cdadbc9..fbe9c9bd56 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,12 @@ NVM-Express user space tooling for Linux. +For more information on the NVM Express standard, see https://nvmexpress.org. + +Subscribe to linux-nvme@lists.infradead.org for Linux NVMe discussions and +development. The list is archived at +https://lists.infradead.org/mailman/listinfo/linux-nvme + [![Coverity Scan Build Status](https://scan.coverity.com/projects/24883/badge.svg)](https://scan.coverity.com/projects/linux-nvme-nvme-cli) [![codecov](https://codecov.io/gh/linux-nvme/nvme-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/linux-nvme/nvme-cli) ![MesonBuild](https://github.com/linux-nvme/nvme-cli/actions/workflows/build.yml/badge.svg) @@ -23,6 +29,11 @@ libnvme: nvme-cli uses meson as its build system. There is more than one way to configure and build the project to accommodate environments with an older version of meson. +A minimal build requires: +- gcc (or clang) +- ninja +- meson + If you build on a relatively modern system, either use meson directly or the Makefile wrapper. @@ -44,6 +55,33 @@ built as part of nvme-cli. | libnvme, libnvme-mi | integrated | No external dependency, included in nvme-cli | | json-c | optional | Recommended; without it, all plugins are disabled and json-c output format is disabled | +### Optional feature dependencies + +The following optional libraries unlock additional features. Each can be +explicitly enabled (`-Doption=enabled`) or disabled (`-Doption=disabled`); +the default is `auto` (use if found) unless noted otherwise. + +| Option | Default | Feature unlocked | +|--------|---------|-----------------| +| `json-c` | `auto` | `/etc/nvme/config.json` parsing; all vendor plugins; JSON output format | +| `openssl` | `auto` | TLS over NVMe-TCP; host authentication | +| `keyutils` | `auto` | Key management for NVMe-oF authentication | +| `libdbus` | `disabled` | End-point discovery for NVMe-MI | +| `liburing` | `disabled` | Get-log-page via io_uring passthrough | +| `python` | `auto` | Python bindings for libnvme | + +Example: explicitly disable Python bindings: + +```shell +$ meson setup .build -Dpython=disabled +``` + +Options specific to nvme-cli are defined in [`meson_options.txt`](meson_options.txt). +To see the full list of available options, including meson built-ins: + +```shell +$ meson configure .build +``` ### Build with meson @@ -77,6 +115,18 @@ $ meson compile -C .build # meson install -C .build ``` +To build a static library instead of a shared one: + +```shell +$ meson setup --default-library=static .build +``` + +#### Running unit tests + +```shell +$ meson test -C .build +``` + #### Installation paths By default, meson installs everything under `/usr/local` (executables in @@ -103,6 +153,31 @@ optimizations for a production install: $ meson setup .build --prefix /usr --sysconfdir /etc --buildtype release ``` +#### Debug and sanitizer builds + +To configure a build for debugging (optimizations off, debug symbols on): + +```shell +$ meson setup .build --buildtype=debug +``` + +To enable address sanitizer (detects memory errors at runtime): + +```shell +$ meson setup .build -Db_sanitize=address +``` + +When using the sanitizer, `libasan.so` must be preloaded if you encounter +linking issues: + +```shell +$ meson setup .build -Db_sanitize=address && \ + LD_PRELOAD=/lib64/libasan.so.6 ninja -C .build test +``` + +The undefined behavior sanitizer is also supported: `-Db_sanitize=undefined`. +To enable both: `-Db_sanitize=address,undefined`. + ### Build with build.sh wrapper The `scripts/build.sh` is used for the CI build but can also be used for @@ -213,165 +288,16 @@ is available as part of the `meta-openembedded` layer collection. `nvme-cli` is available as a [buildroot](https://buildroot.org) package. The package is named `nvme`. -## Developers - -You may wish to add a new command or possibly an entirely new plug-in -for some special extension outside the spec. - -This project provides macros that help generate the code for you. If -you're interested in how that works, it is very similar to how trace -events are created by Linux kernel's 'ftrace' component. - -### Add command to existing built-in - -The first thing to do is define a new command entry in the command -list. This is declared in nvme-builtin.h. Simply append a new "ENTRY" into -the list. The ENTRY normally takes three arguments: the "name" of the -subcommand (this is what the user will type at the command line to invoke -your command), a short help description of what your command does, and the -name of the function callback that you're going to write. Additionally, -you can declare an alias name of the subcommand with a fourth argument, if -needed. - -After the ENTRY is defined, you need to implement the callback. It takes -four arguments: argc, argv, the command structure associated with the -callback, and the plug-in structure that contains that command. The -prototype looks like this: - - ```c - int f(int argc, char **argv, struct command *command, struct plugin *plugin); - ``` - -The argc and argv are adjusted from the command line arguments to start -after the sub-command. So if the command line is "nvme foo --option=bar", -the argc is 1 and argv starts at "--option". - -You can then define argument parsing for your sub-command's specific -options then do some command-specific action in your callback. - -### Add a new plugin - -The nvme-cli provides macros to make defining a new plug-in simpler. You -can certainly do all this by hand if you want, but it should be easier -to get going using the macros. To start, first create a header file -to define your plugin. This is where you will give your plugin a name, -description, and define all the sub-commands your plugin implements. - -The macros must appear in a specific order within the header file. The following -is a basic example on how to start this: - -File: foo-plugin.h -```c -#undef CMD_INC_FILE -#define CMD_INC_FILE plugins/foo/foo-plugin - -#if !defined(FOO) || defined(CMD_HEADER_MULTI_READ) -#define FOO - -#include "cmd.h" - -PLUGIN(NAME("foo", "Foo plugin"), - COMMAND_LIST( - ENTRY("bar", "foo bar", bar) - ENTRY("baz", "foo baz", baz) - ENTRY("qux", "foo qux", qux) - ) -); - -#endif - -#include "define_cmd.h" -``` - -In order to have the compiler generate the plugin through the xmacro -expansion, you need to include this header in your source file, with -a pre-defining macro directive to create the commands. - -To get started from the above example, we just need to define "CREATE_CMD" -and include the header: - -File: foo-plugin.c -```c -#include "nvme.h" - -#define CREATE_CMD -#include "foo-plugin.h" -``` - -After that, you just need to implement the functions you defined in each -ENTRY, then append the object file name to the meson.build "sources". - -### Updating the libnvme accessor functions - -libnvme exposes auto-generated getter/setter accessor functions for its -ABI-stable opaque structs. Two sets of accessors are maintained: - -| Set | Input header | Generated files | -|-----|-------------|-----------------| -| Common NVMe | `libnvme/src/nvme/private.h` | `src/nvme/accessors.{h,c}`, `src/accessors.ld` | -| NVMe-oF | `libnvme/src/nvme/private-fabrics.h` | `src/nvme/accessors-fabrics.{h,c}`, `src/accessors-fabrics.ld` | - -The generated `.h` and `.c` files are committed to the source tree and are -**not** regenerated during a normal build. To regenerate after modifying a -`/*!generate-accessors*/` struct: - -```shell -$ meson compile -C .build update-accessors -``` - -See [`libnvme/README.md`](libnvme/README.md#accessor-generation) for full -details, including how to maintain the `.ld` version-script files. - ## Dependency libnvme depends on the `/sys/class/nvme-subsystem` interface which was introduced in Linux kernel v4.15. nvme-cli requires kernel v4.15 or later. -## How to contribute - -There are two ways to send code changes to the project. The first one -is by sending the changes to linux-nvme@lists.infradead.org. The -second one is by posting a pull request on Github. In both cases -please follow the Linux contributions guidelines as documented in -[Submitting patches](https://docs.kernel.org/process/submitting-patches.html). - -That means the changes should be a clean series (no merges should be -present in a Github PR for example) and every commit should build. +## Contributing -See also [How to create a pull request on GitHub](https://opensource.com/article/19/7/create-pull-request-github). - -### How to clean up your series before creating a PR - -This example here assumes the changes are in a branch called -fix-something, which branched away from master in the past. In the -meantime the upstream project has changed, hence the fix-something -branch is not based on the current HEAD. Before posting the PR, the -branch should be rebased on the current HEAD and retest everything. - -For example, rebasing can be done by the following steps - -```shell -# Update master branch -# upstream == https://github.com/linux-nvme/nvme-cli.git -$ git switch master -$ git fetch --all -$ git reset --hard upstream/master - -# Make sure all dependencies are up to date and make a sanity build -$ meson subprojects update -$ ninja -C .build - -# Go back to the fix-something branch -$ git switch fix-something - -# Rebase it to the current HEAD -$ git rebase master -[fixup all merge conflicts] -[retest] - -# Push your changes to Github and trigger a PR -$ git push -u origin fix-something -``` +For information on adding commands, adding plugins, API naming conventions, +commit guidelines, and the pull request workflow, see +[CONTRIBUTING.md](CONTRIBUTING.md). ## Persistent and volatile configuration @@ -422,133 +348,7 @@ extension in `/run/nvme` and write the contents to this file. When finished, use `rename` to add the `.json` file name extension. This ensures nvme-cli only sees the complete file. -## Testing - -For testing purposes, an x86_64 static build from the current HEAD is available -[here](https://monom.org/linux-nvme/upload/nvme-cli-latest-x86_64). - -## Container-Based Debugging and CI Build Reproduction - -The nvme-cli project provides prebuilt CI containers that allow you to locally -reproduce GitHub Actions builds for debugging and development. These containers -mirror the environments used in the official CI workflows. - -CI Containers Repository: -[linux-nvme/ci-containers](https://github.com/linux-nvme/ci-containers) - -CI Build Workflow Reference: -[libnvme-build.yml](https://github.com/linux-nvme/nvme-cli/blob/master/.github/workflows/libnvme-build.yml) - -### 1. Pull a CI Container - -All CI containers are published as OCI/Docker images. - -Example: Debian latest CI image: - -```bash -docker pull ghcr.io/linux-nvme/debian:latest -``` - -Or with Podman: - -```bash -podman pull ghcr.io/linux-nvme/debian:latest -``` - -### 2. Start the Container and Log In - -Start an interactive shell inside the container: - -```bash -docker run --rm -it \ - --name nvme-cli-debug \ - ghcr.io/linux-nvme/debian:latest \ - bash -``` - -Or with Podman: - -```bash -podman run --rm -it \ - --name nvme-cli-debug \ - ghcr.io/linux-nvme/debian:latest \ - bash -``` - -You are now logged into the same environment used by CI. - -### 3. Clone the nvme-cli Repository - -Inside the running container: - -```bash -git clone https://github.com/linux-nvme/nvme-cli.git -cd nvme-cli -``` - -(Optional) Check out a specific branch or pull request: - -```bash -git checkout -``` - -### 4. Run the CI Build Script - -The GitHub Actions workflow uses `scripts/build.sh`. To reproduce the CI build locally: - -```bash -./scripts/build.sh -``` - -Build artifacts remain inside the container unless a host volume is mounted. - -### 5. Cross-Build Example - -The CI supports cross compilation using a dedicated cross-build container. - -#### 5.1 Pull the Cross-Build Container - -```bash -docker pull ghcr.io/linux-nvme/ubuntu-cross-s390x:latest -``` - -Or with Podman: - -```bash -podman pull ghcr.io/linux-nvme/ubuntu-cross-s390x:latest -``` - -#### 5.2 Start the Cross-Build Container - -```bash -docker run --rm -it \ - --name nvme-cli-cross \ - ghcr.io/linux-nvme/ubuntu-cross-s390x:latest \ - bash -``` - -Or with Podman: - -```bash -podman run --rm -it \ - --name nvme-cli-cross \ - ghcr.io/linux-nvme/ubuntu-cross-s390x:latest \ - bash -``` - -#### 5.3 Clone the Repository - -```bash -git clone https://github.com/linux-nvme/nvme-cli.git -cd nvme-cli -``` - -#### 5.4 Run a Cross Build - -Example: Cross-build for `s390x`: - -```bash -./scripts/build.sh -b release -c gcc -t s390x cross -``` +## Testing and CI -The exact supported targets depend on the toolchains installed in the container. +For pre-built binaries, CI build reproduction, and container-based debugging, +see [TESTING.md](TESTING.md). diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000000..728f8ed227 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,133 @@ + +# Testing and CI + +## Pre-built binary + +For quick testing, an x86_64 static build from the current HEAD is available +[here](https://monom.org/linux-nvme/upload/nvme-cli-latest-x86_64). + +## Container-Based Debugging and CI Build Reproduction + +The nvme-cli project provides prebuilt CI containers that allow you to locally +reproduce GitHub Actions builds for debugging and development. These containers +mirror the environments used in the official CI workflows. + +CI Containers Repository: +[linux-nvme/ci-containers](https://github.com/linux-nvme/ci-containers) + +CI Build Workflow Reference: +[libnvme-build.yml](https://github.com/linux-nvme/nvme-cli/blob/master/.github/workflows/libnvme-build.yml) + +### 1. Pull a CI Container + +All CI containers are published as OCI/Docker images. + +Example: Debian latest CI image: + +```bash +docker pull ghcr.io/linux-nvme/debian:latest +``` + +Or with Podman: + +```bash +podman pull ghcr.io/linux-nvme/debian:latest +``` + +### 2. Start the Container and Log In + +Start an interactive shell inside the container: + +```bash +docker run --rm -it \ + --name nvme-cli-debug \ + ghcr.io/linux-nvme/debian:latest \ + bash +``` + +Or with Podman: + +```bash +podman run --rm -it \ + --name nvme-cli-debug \ + ghcr.io/linux-nvme/debian:latest \ + bash +``` + +You are now logged into the same environment used by CI. + +### 3. Clone the nvme-cli Repository + +Inside the running container: + +```bash +git clone https://github.com/linux-nvme/nvme-cli.git +cd nvme-cli +``` + +(Optional) Check out a specific branch or pull request: + +```bash +git checkout +``` + +### 4. Run the CI Build Script + +The GitHub Actions workflow uses `scripts/build.sh`. To reproduce the CI build locally: + +```bash +./scripts/build.sh +``` + +Build artifacts remain inside the container unless a host volume is mounted. + +### 5. Cross-Build Example + +The CI supports cross compilation using a dedicated cross-build container. + +#### 5.1 Pull the Cross-Build Container + +```bash +docker pull ghcr.io/linux-nvme/ubuntu-cross-s390x:latest +``` + +Or with Podman: + +```bash +podman pull ghcr.io/linux-nvme/ubuntu-cross-s390x:latest +``` + +#### 5.2 Start the Cross-Build Container + +```bash +docker run --rm -it \ + --name nvme-cli-cross \ + ghcr.io/linux-nvme/ubuntu-cross-s390x:latest \ + bash +``` + +Or with Podman: + +```bash +podman run --rm -it \ + --name nvme-cli-cross \ + ghcr.io/linux-nvme/ubuntu-cross-s390x:latest \ + bash +``` + +#### 5.3 Clone the Repository + +```bash +git clone https://github.com/linux-nvme/nvme-cli.git +cd nvme-cli +``` + +#### 5.4 Run a Cross Build + +Example: Cross-build for `s390x`: + +```bash +./scripts/build.sh -b release -c gcc -t s390x cross +``` + +The exact supported targets depend on the toolchains installed in the container. diff --git a/libnvme/README.md b/libnvme/README.md deleted file mode 100644 index 4b09cfc2a3..0000000000 --- a/libnvme/README.md +++ /dev/null @@ -1,270 +0,0 @@ - -# libnvme - -![PyBuild](https://github.com/linux-nvme/nvme-cli/actions/workflows/libnvme-release-python.yml/badge.svg) -[![PyPI](https://img.shields.io/pypi/v/libnvme)](https://pypi.org/project/libnvme/) -[![PyPI - Wheel](https://img.shields.io/pypi/wheel/libnvme)](https://pypi.org/project/libnvme/) -[![codecov](https://codecov.io/gh/linux-nvme/nvme-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/linux-nvme/nvme-cli) -[![Read the Docs](https://img.shields.io/readthedocs/libnvme)](https://libnvme.readthedocs.io/en/latest/) - -This is the libnvme development C library. libnvme provides type -definitions for NVMe specification structures, enumerations, and bit -fields, helper functions to construct, dispatch, and decode commands -and payloads, and utilities to connect, scan, and manage nvme devices -on a Linux system. - -The public specification is the authority to resolve any protocol -discrepancies with this library. For more info on NVM Express, please -see: - - https://nvmexpress.org - -Subscribe to linux-nvme@lists.infradead.org for linux-nvme related -discussions and development for both kernel and userspace. The list is -archived here: - - https://lists.infradead.org/mailman/listinfo/linux-nvme - -# License - -Except where otherwise stated, all software contained within this repo -is currently licensed LGPL-2.1-or-later, see COPYING for more -information. - -Keith Busch 2020-02-06 - ------- - -# Dependency - -libnvme depends on minimum Linux kernel version v4.15, which -introduced the /sys/class/nvme-subsystem. - -# Build from source -## Prerequisite - -A minimal build depends on a set of build tools - - - gcc - - ninja - - meson - -Not all feature will be present with such configuration, e.g. -the fabrics part of the library wont support authentication or -TLS over the nvme-tcp transport. - -To enable the optional features install following libraries - -`/etc/nvme/config.json`` support: - - json-c (recommend) - -Authentication and TLS over nvme-tcp: - - openssl - - keyutils - -End point discovery for MI - - libdbus - -Python bindings - - Python 3 interpreter - - Python 3 development libraries - -## Minimal on embedded builds - -The reference implemention of the Meson specification is in Python 3. Installing -or porting this dependency is not really feasible for embedded project. Though -there are two project which implement the Ninja and the Meson API in pure C99 - - - samurai: https://github.com/michaelforney/samurai.git - - muon: https://git.sr.ht/~lattis/muon - -The CI build helper script `scripts/build.sh` is able to setup and build this -project in a minimal setup using samurai and muon and thus only depending on: -- gcc -- make -- git - -`scripts/build.sh -m muon` - -## To compile libnvme - -To `configure` the project: - -``` -meson setup .build -``` - -Which will default to build a shared library. To configure for static libraries call - -``` -meson setup --default-library=static .build -``` - -One nice feature of meson is that it doesn't mix build artifacts -(e.g. `*.o`, `*.so`, etc.) with source code. In the above example, -"`.build`" is the name of the directory where the build configuration -as well as all the build artifacts will be saved. This directory can -be named anything as long as it's not an existing source directory. To -completely "clean" all the build artifacts, one need only delete the -`.build` directory. - -To compile: - -``` -meson compile -C .build -``` - -## To install libnvme - -To install `libnvme`: - -``` -meson install -C .build -``` - -## To run unit tests - -To run unit tests: - -``` -meson test -C .build -``` - -## To purge everything - -To completely clean all build artifacts, including the build configuration. - -``` -rm -rf .build -``` - -## Supported build options - -A few build options can be specified on the command line when invoking meson. - -| Option | Values [default] | Description | -| ----------- | ------------------------- | ------------------------------------------------------------ | -| version-tag | none | Overwrite the git version string in the binary | -| htmldir | none | Installation directory for the HTML documentation | -| rstdir | none | Installation directory for the RST documentation | -| docs | [false], html, man, rst, all | Install documentation | -| docs-build | [false], true | Enable build documentation | -| python | [auto], enabled, disabled | Whether to build the Python bindings. When set to `auto`, the default, meson will check for the presence of the tools and libraries (e.g. `swig`) required to build the Python bindings. If found, meson will configure the project to build the Python bindings. If a tool or library is missing, then the Python bindings won't be built. Setting this to `enabled`, forces the Python bindings to be built. When set to `disabled`, meson will configure the project to not build the Python bindings.
Example: `meson setup .build -Dpython=disabled` | -| openssl | [auto], enabled, disabled | Enables OpenSSL dependent features (e.g. TLS over TCP), adds build dependency on OpenSSL | -| libdbus | auto, enabled, [disabled] | Enables D-Bus dependent features (libnvme-mi: End point discovery), adds build dependency on libdbus | -| json-c | [auto], enabled, disabled | (recommended) Enables JSON-C dependend features (e.g. config.json parsing), adds build depdency on json-c | -| keyutils | [auto], enabled, disabled | Enables keyutils dependent features (e.g. authentication), adds build dependency on keyutils | -| liburing | auto, enabled, [disabled] | Enables liburing dependent features (e.g. get log page by uring cmd), adds build depdency on liburing, very questionable feature. Don't enable it | - -See the full configuration options with - -```bash -meson configure .build -``` - -### Changing the build options from the command-line (i.e. w/o modifying any files) - -To configure a build for debugging purposes (i.e. optimization turned -off and debug symbols enabled): - -```bash -meson setup .build --buildtype=debug -``` - -To enable address sanitizer (advanced debugging of memory issues): - -```bash -meson setup .build -Db_sanitize=address -``` - -This option adds `-fsanitize=address` to the gcc options. The tests can then be run normally (`meson test -C .build`). - -Note that when using the sanitize feature, the library `libasan.so` must be available and must be the very first library loaded when running an executable. If experiencing linking issues, you can ensure that `libasan.so` gets loaded first with the `LD_PRELOAD` environment variable as follows: - -``` -meson setup .build -Db_sanitize=address && LD_PRELOAD=/lib64/libasan.so.6 ninja -C .build test -``` - -It's also possible to enable the undefined behavior sanitizer with `-Db_sanitize=undefined`. To enable both, use `-Db_sanitize=address,undefined`. - -## Accessor generation - -Some public structs in libnvme use auto-generated setter/getter accessor -functions to provide ABI stability. Callers never access struct members -directly; they use the generated accessors instead. The generated files are -committed to the source tree and are **not** regenerated during a normal build. - -Two sets of accessors are maintained — one for common NVMe structs and one for -NVMe-oF-specific structs. The split exists so that non-fabrics (e.g. embedded -or PCIe-only) builds can exclude all fabrics code entirely. - -| Meson target | Input header | Generated files | -|---|---|---| -| `update-common-accessors` | `src/nvme/private.h` | `src/nvme/accessors.{h,c}`, `src/accessors.ld` | -| `update-fabrics-accessors` | `src/nvme/private-fabrics.h` | `src/nvme/accessors-fabrics.{h,c}`, `src/accessors-fabrics.ld` | - -### When to regenerate - -Regeneration is needed whenever a `/*!generate-accessors*/` struct in -`private.h` or `private-fabrics.h` has a member added, removed, or renamed. - -### How to regenerate - -To regenerate both sets at once: - -```bash -meson compile -C .build update-accessors -``` - -Or regenerate only one set: - -```bash -meson compile -C .build update-common-accessors -meson compile -C .build update-fabrics-accessors -``` - -The script atomically updates the `.h` and `.c` files when their content -changes. Commit the updated files afterward: - -```bash -git add libnvme/src/nvme/accessors.h libnvme/src/nvme/accessors.c -git add libnvme/src/nvme/accessors-fabrics.h libnvme/src/nvme/accessors-fabrics.c -git commit -m "libnvme: regenerate accessors following changes" -``` - -### Maintaining the .ld version-script files - -The `.ld` files (`src/accessors.ld` and `src/accessors-fabrics.ld`) are GNU -linker version scripts that control which accessor symbols are exported from -the shared library and under which ABI version label they were introduced -(e.g. `LIBNVME_ACCESSORS_3`, `LIBNVMF_ACCESSORS_3`). - -These files are **not** updated automatically, because each new symbol must be -placed in the correct version section by the maintainer. Adding a symbol to an -already-published version section would break binary compatibility for -existing users of the library. - -When the generator detects that the symbol list has drifted, it prints a -report like the following: - -``` -WARNING: accessors.ld needs manual attention. - - Symbols to ADD (new version section, e.g. LIBNVME_ACCESSORS_X_Y): - libnvme_ctrl_get_new_field - libnvme_ctrl_set_new_field -``` - -New symbols must be added to a **new** version section that chains the -previous one. For example, if the current latest section is -`LIBNVME_ACCESSORS_3`, add: - -``` -LIBNVME_ACCESSORS_4 { - global: - libnvme_ctrl_get_new_field; - libnvme_ctrl_set_new_field; -} LIBNVME_ACCESSORS_3; -``` - -Then commit the updated `.ld` file together with the regenerated source files.