summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md335
1 files changed, 335 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1113b1e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,335 @@
+# nvme-cli
+![Coverity Scan Build Status](https://scan.coverity.com/projects/24883/badge.svg)
+![MesonBuild](https://github.com/linux-nvme/nvme-cli/actions/workflows/build.yml/badge.svg)
+![GitHub](https://img.shields.io/github/license/linux-nvme/nvme-cli)
+
+NVM-Express user space tooling for Linux.
+
+## Build from source
+
+nvme-cli uses meson as build system. There is more than one way to configure and
+build the project in order to mitigate meson dependency on the build
+environment.
+
+If you build on a relative modern system, either use meson directly or the
+Makefile wrapper.
+
+Older distros might ship a too old version of meson, in this case it's possible
+to build the project using [samurai](https://github.com/michaelforney/samurai)
+and [muon](https://github.com/annacrombie/muon). Both build tools have only a
+minimal dependency on the build environment. Too easy this step there is a build
+script which helps to setup a build environment.
+
+### nvme-cli dependencies:
+
+ | Library | Dependency | Notes |
+ |---------|------------|-------|
+ | libnvme, libnvme-mi| yes | be either installed or included into the build via meson fallback feature |
+ | json-c | optional | recommended, without all plugins are disabled and json-c output format is disabled |
+
+
+### Build with meson
+
+#### Configuring
+
+In case libnvme is not installed on the system, it possible to use meson's
+fallback feature to resolve the dependency.
+
+ $ meson setup --force-fallback-for=libnvme .build
+
+If the libnvme is already installed on the system meson is using pkg-config to
+find the dependency. In this case a plain setup call is enough:
+
+ $ meson setup .build
+
+With meson's --wrap-mode argument it's possible to control if the additional
+dependencies should also resolved or not. The options are
+
+ --wrap-mode {default,nofallback,nodownload,forcefallback,nopromote}
+
+Note for nvme-cli the 'default' is set to nofallback.
+
+#### Building
+
+ $ meson compile -C .build
+
+#### Installing
+
+ # meson install -C .build
+
+### Build with build.sh wrapper
+
+The `scripts/build.sh` is used for the CI build but can also be used for
+configuring and building the project.
+
+Running `scripts/build.sh` without any argument builds the project in the
+default configuration (meson, gcc and defaults)
+
+It's possible to change the compiler to clang
+
+`scripts/builds.sh -c clang`
+
+or enabling all the fallbacks
+
+`scripts/build.sh fallback`
+
+### Minimal static build with muon
+
+`scripts/build.sh -m muon` will download and build `samurai` and `muon` instead
+using `meson` to build the project. This reduces the dependency on the build
+environment to:
+- gcc
+- make
+- git
+
+Furthermore, this configuration will produce a static binary.
+
+### Build with Makefile wrapper
+
+There is a Makefile wrapper for meson for backwards compatibility
+
+ $ make
+ # make install
+
+Note in this case libnvme needs to be installed by hand first.
+
+RPM build support via Makefile that uses meson
+
+ $ make rpm
+
+Static binary(no dependency) build support via Makefile that uses meson
+
+ $ make static
+
+If not sure how to use, find the top-level documentation with:
+
+ $ man nvme
+
+Or find a short summary with:
+
+ $ nvme help
+
+## Distro Support
+
+Many popular distributions (Alpine, Arch, Debian, Fedora, FreeBSD, Gentoo,
+Ubuntu, Nix(OS), openSUSE, ...) and the usual package name is nvme-cli.
+
+#### OpenEmbedded/Yocto
+
+An [nvme-cli recipe](https://layers.openembedded.org/layerindex/recipe/88631/)
+is available as part of the `meta-openembeded` layer collection.
+
+#### Buildroot
+
+`nvme-cli` is available as [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 subcommand with 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 *cmd, 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 define 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.
+
+There is a very important order on how to define the plugin. 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 quz", 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
+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".
+
+## meson tips
+
+In case meson doesn't find libnvme header files (via pkg-config) it
+will fallback using subprojects. meson checks out libnvme in
+subprojects directory as git tree once to the commit level specified
+in the libnvme.wrap file revision parm. After this initial checkout,
+the libnvme code level will not change unless explicitly told. That
+means if the current branch is updated via git, the subprojects/libnvme
+branch will not updated accordingly. To update it, either use the
+normal git operations or the command:
+
+ $ meson subprojects update
+
+## Dependency
+
+libnvme depends on the /sys/class/nvme-subsystem interface which was
+introduced in the Linux kernel release v4.15. Hence nvme-cli 2.x is
+only working on kernels >= v4.15. For older kernels nvme-cli 1.x is
+recommended to be used.
+
+## 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
+
+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 https://opensource.com/article/19/7/create-pull-request-github
+
+### How to cleanup your series before creating 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 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
+```
+
+## Persistent, volatile configuration
+
+Persistent configurations can be stored in two different locations: either in
+the file `/etc/nvme/discovery.conf` using the old style, or in the file
+`/etc/nvme/config.json` using the new style.
+
+On the other hand, volatile configurations, such as those obtained from
+third-party tools like `nvme-stats` or `blktests'` can be stored in the
+`/run/nvme` directory. When using the `nvme-cli` tool, all these configurations
+are combined into a single configuration that is used as input.
+
+The volatile configuration is particularly useful for coordinating access to the
+global resources among various components. For example, when executing
+`blktests` for the FC transport, the `nvme-cli` udev rules can be triggered. To
+prevent interference with a test, `blktests` can create a JSON configuration
+file in `/run/nvme` to inform `nvme-cli` that it should not perform any actions
+triggered from the udev context. This behavior can be controlled using the
+`--context` argument.
+
+For example a `blktests` volatile configuration could look like:
+
+```json
+[
+ {
+ "hostnqn": "nqn.2014-08.org.nvmexpress:uuid:242d4a24-2484-4a80-8234-d0169409c5e8",
+ "hostid": "242d4a24-2484-4a80-8234-d0169409c5e8",
+ "subsystems": [
+ {
+ "application": "blktests",
+ "nqn": "blktests-subsystem-1",
+ "ports": [
+ {
+ "transport": "fc",
+ "traddr": "nn-0x10001100aa000001:pn-0x20001100aa000001",
+ "host_traddr": "nn-0x10001100aa000002:pn-0x20001100aa000002"
+ }
+ ]
+ }
+ ]
+ }
+]
+```
+
+Note when updating the volatile configuration during runtime, it should done in
+a an atomic way. For example create a temporary file without the `.json` file
+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 a x86_64 AppImage is build from the current HEAD and is
+available here:
+
+https://monom.org/linux-nvme/upload/AppImage/nvme-cli-latest-x86_64.AppImage