1
0
Fork 0

Adding upstream version 1.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-15 08:44:15 +01:00
parent 809e3412a9
commit 336fe81026
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
743 changed files with 51081 additions and 0 deletions

21
.github/workflows/doc.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: libnvme documenation CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
kernel_doc_job:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v2
- name: Check documentation format
run: |
API_FILES="fabrics.h filters.h ioctl.h linux.h tree.h types.h"
for file in $API_FILES; do
./doc/kernel-doc -v -none src/nvme/$file 2>&1 | sed -r 's/^([^:]+):([0-9]+): (warning|error):/::\3 file=\1,line=\2::/g'
done
shell: bash

69
.github/workflows/meson.yml vendored Normal file
View file

@ -0,0 +1,69 @@
name: libnvme meson CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build-disto:
runs-on: ubuntu-latest
steps:
- name: install libraries
run: sudo apt-get install libjson-c-dev
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
- uses: BSFishy/meson-build@v1.0.3
with:
setup-options: --werror
options: --verbose
action: test
# Preserve meson's log file on failure
- uses: actions/upload-artifact@v1
if: failure()
with:
name: Linux_Meson_Testlog
path: build/meson-logs/testlog.txt
build-fallback:
runs-on: ubuntu-latest
steps:
- name: install libraries
run: sudo apt-get remove -y libssl-dev
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
- uses: BSFishy/meson-build@v1.0.3
with:
setup-options: --werror
options: --verbose
action: test
meson-version: 0.61.2
# Preserve meson's log file on failure
- uses: actions/upload-artifact@v1
if: failure()
with:
name: Linux_Meson_log
path: build/meson-logs/meson-log.txt
code-coverage:
runs-on: ubuntu-latest
steps:
- name: install libraries
run: sudo apt-get install libjson-c-dev lcov
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
- uses: BSFishy/meson-build@v1.0.3
with:
setup-options: -Db_coverage=true --werror
options: --verbose
# Can't use 'coverage' here, see https://github.com/BSFishy/meson-build/issues/4
action: test
- name: Generate Coverage Report
# Can't use meson here, see https://github.com/mesonbuild/meson/issues/7895
run: ninja -C build coverage --verbose
- uses: codecov/codecov-action@v1
with:
fail_ci_if_error: false

67
.github/workflows/python-publish.yml vendored Normal file
View file

@ -0,0 +1,67 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Build and upload to PyPI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build_wheels:
name: Build wheels manylinux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build wheels
uses: pypa/cibuildwheel@v2.3.1
env:
CIBW_REPAIR_WHEEL_COMMAND_LINUX: ""
CIBW_SKIP: "*-musllinux_*"
CIBW_BEFORE_BUILD_LINUX: yum install -y openssl-devel libuuid-devel json-c-devel
CIBW_BUILD_VERBOSITY: 1
- uses: actions/upload-artifact@v2
with:
path: ./wheelhouse/*.whl
retention-days: 5
build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build sdist
run: pipx run build --sdist
- uses: actions/upload-artifact@v2
with:
path: dist/*.tar.gz
retention-days: 5
upload_pypi:
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- uses: actions/download-artifact@v2
with:
name: artifact
path: dist
- name: Publish package to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/

15
.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
a.out
*.o
*.ol
*.os
*~
*.swp
*.a
*.so.*
cscope.*
.build
subprojects/*
!subprojects/*.wrap

502
COPYING Normal file
View file

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

43
Makefile Normal file
View file

@ -0,0 +1,43 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of libnvme.
# Copyright (c) 2021 Dell Inc.
#
# Authors: Martin Belanger <Martin.Belanger@dell.com>
#
NAME := libnvme
.DEFAULT_GOAL := ${NAME}
BUILD-DIR := .build
${BUILD-DIR}:
meson $@
@echo "Configuration located in: $@"
@echo "-------------------------------------------------------"
.PHONY: ${NAME}
${NAME}: ${BUILD-DIR}
ninja -C ${BUILD-DIR}
.PHONY: clean
clean:
ifneq ("$(wildcard ${BUILD-DIR})","")
ninja -C ${BUILD-DIR} -t $@
endif
.PHONY: purge
purge:
ifneq ("$(wildcard ${BUILD-DIR})","")
rm -rf ${BUILD-DIR}
endif
.PHONY: install dist
install dist: ${BUILD-DIR}
cd ${BUILD-DIR} && meson $@
.PHONY: test
test: ${BUILD-DIR}
ninja -C ${BUILD-DIR} $@
.PHONY: rpm
rpm: dist
rpmbuild -ba ${BUILD-DIR}/libnvme.spec

188
README.md Normal file
View file

@ -0,0 +1,188 @@
# libnvme
![MesonBuild](https://github.com/linux-nvme/libnvme/actions/workflows/meson.yml/badge.svg)
![PyBuild](https://github.com/linux-nvme/libnvme/actions/workflows/python-publish.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/)
![GitHub](https://img.shields.io/github/license/linux-nvme/libnvme)
[![codecov](https://codecov.io/gh/linux-nvme/libnvme/branch/master/graph/badge.svg)](https://codecov.io/gh/linux-nvme/libnvme)
[![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
discrepencies with this library. For more info on NVM Express, please
see:
http://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:
http://lists.infradead.org/mailman/listinfo/linux-nvme
# License
Except where otherwise stated, all software contained within this repo
is currently licensed LGPL, see COPYING for more information.
Keith Busch 2020-02-06
------
# Building with meson
## What is the meson build system?
Here's an excerpt from the meson web site: *Meson is **an open source
build system** meant to be both extremely fast, and, even more
importantly, as user friendly as possible. The main design point of
Meson is that every moment a developer spends writing or debugging
build definitions is a second wasted.*
Several well-known projects such as `systemd` and `Gnome` use meson as
their build system. A summary of projects using meson can be found
[here](https://mesonbuild.com/Users.html). For more info on meson,
please consult the following sites:
**Wiki page**: https://en.wikipedia.org/wiki/Meson_(software)
**meson documentation**: https://mesonbuild.com/
**meson repo**: https://github.com/mesonbuild/meson
## Prerequisite
First, install meson.
**Debian / Ubuntu**:
```bash
sudo apt-get install meson
```
**Fedora / Red Hat**:
```bash
sudo dnf install meson
```
## To compile libnvme
Using meson is similar to projects that use a `configure` script before running `make`.
To `configure` the project:
```
meson .build
```
Which will default to build a shared library. To configure for static libraries call
```
meson .build --default-library=static
```
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:
```
cd .build
ninja
```
Or:
```
ninja -C .build
```
## To install libnvme
To install `libnvme`:
```
cd .build
meson install
```
## To run unit tests
To run unit tests:
```
cd .build
meson test
```
## To clean after a build
To perform the equivalent of a `make clean` without deleting the build configuration.
```
cd .build
ninja -t clean
```
Or:
```
ninja -C .build -t clean
```
## 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 |
| ------ | ------------------- | ------------------------------------------------------------ |
| man | true, [false] | Instruct meson to configure the project to build the `libnvme` documentation. <br />Example: `meson .build -Dman=true` |
| python | [auto], true, false | 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 `true`, forces the Python bindings to be built. When set to `false`, meson will configure the project to not build the Python bindings.<br />Example: `meson .build -Dpython=false` |
### 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 .build -Dbuildtype=debug
```
To enable address sanitizer (advanced debugging of memory issues):
```bash
meson .build -Db_sanitize=address
```
This option adds `-fsanitize=address` to the gcc options. 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. Ensuring that `libasan.so` gets loaded first can be achieved with the `LD_PRELOAD` environment variable as follows:
```
meson .build -Db_sanitize=address && LD_PRELOAD=/lib64/libasan.so.6 ninja -C .build test
```
To list configuration options that are available and possible values:
```bash
meson configure .build
```

View file

@ -0,0 +1 @@
../../licenses/CC0

View file

@ -0,0 +1,46 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* array_size - routine for safely deriving the size of a visible array.
*
* This provides a simple ARRAY_SIZE() macro, which (given a good compiler)
* will also break compile if you try to use it on a pointer.
*
* This can ensure your code is robust to changes, without needing a gratuitous
* macro or constant.
*
* Example:
* // Outputs "Initialized 32 values\n"
* #include <ccan/array_size/array_size.h>
* #include <stdlib.h>
* #include <stdio.h>
*
* // We currently use 32 random values.
* static unsigned int vals[32];
*
* int main(void)
* {
* unsigned int i;
* for (i = 0; i < ARRAY_SIZE(vals); i++)
* vals[i] = random();
* printf("Initialized %u values\n", i);
* return 0;
* }
*
* License: CC0 (Public domain)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
return 0;
}
return 1;
}

View file

@ -0,0 +1,26 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_ARRAY_SIZE_H
#define CCAN_ARRAY_SIZE_H
#include "config.h"
#include <ccan/build_assert/build_assert.h>
/**
* ARRAY_SIZE - get the number of elements in a visible array
* @arr: the array whose size you want.
*
* This does not work on pointers, or arrays declared as [], or
* function parameters. With correct compiler support, such usage
* will cause a build error (see build_assert).
*/
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + _array_size_chk(arr))
#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF
/* Two gcc extensions.
* &a[0] degrades to a pointer: a different type from an array */
#define _array_size_chk(arr) \
BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(arr), \
typeof(&(arr)[0])))
#else
#define _array_size_chk(arr) 0
#endif
#endif /* CCAN_ALIGNOF_H */

View file

@ -0,0 +1 @@
../../licenses/CC0

View file

@ -0,0 +1,49 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* build_assert - routines for build-time assertions
*
* This code provides routines which will cause compilation to fail should some
* assertion be untrue: such failures are preferable to run-time assertions,
* but much more limited since they can only depends on compile-time constants.
*
* These assertions are most useful when two parts of the code must be kept in
* sync: it is better to avoid such cases if possible, but seconds best is to
* detect invalid changes at build time.
*
* For example, a tricky piece of code might rely on a certain element being at
* the start of the structure. To ensure that future changes don't break it,
* you would catch such changes in your code like so:
*
* Example:
* #include <stddef.h>
* #include <ccan/build_assert/build_assert.h>
*
* struct foo {
* char string[5];
* int x;
* };
*
* static char *foo_string(struct foo *foo)
* {
* // This trick requires that the string be first in the structure
* BUILD_ASSERT(offsetof(struct foo, string) == 0);
* return (char *)foo;
* }
*
* License: CC0 (Public domain)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0)
/* Nothing. */
return 0;
return 1;
}

View file

@ -0,0 +1,40 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_BUILD_ASSERT_H
#define CCAN_BUILD_ASSERT_H
/**
* BUILD_ASSERT - assert a build-time dependency.
* @cond: the compile-time condition which must be true.
*
* Your compile will fail if the condition isn't true, or can't be evaluated
* by the compiler. This can only be used within a function.
*
* Example:
* #include <stddef.h>
* ...
* static char *foo_to_char(struct foo *foo)
* {
* // This code needs string to be at start of foo.
* BUILD_ASSERT(offsetof(struct foo, string) == 0);
* return (char *)foo;
* }
*/
#define BUILD_ASSERT(cond) \
do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
/**
* BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
* @cond: the compile-time condition which must be true.
*
* Your compile will fail if the condition isn't true, or can't be evaluated
* by the compiler. This can be used in an expression: its value is "0".
*
* Example:
* #define foo_to_char(foo) \
* ((char *)(foo) \
* + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
*/
#define BUILD_ASSERT_OR_ZERO(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
#endif /* CCAN_BUILD_ASSERT_H */

View file

@ -0,0 +1 @@
../../licenses/CC0

View file

@ -0,0 +1,33 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* check_type - routines for compile time type checking
*
* C has fairly weak typing: ints get automatically converted to longs, signed
* to unsigned, etc. There are some cases where this is best avoided, and
* these macros provide methods for evoking warnings (or build errors) when
* a precise type isn't used.
*
* On compilers which don't support typeof() these routines are less effective,
* since they have to use sizeof() which can only distiguish between types of
* different size.
*
* License: CC0 (Public domain)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
#if !HAVE_TYPEOF
printf("ccan/build_assert\n");
#endif
return 0;
}
return 1;
}

View file

@ -0,0 +1,64 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_CHECK_TYPE_H
#define CCAN_CHECK_TYPE_H
#include "config.h"
/**
* check_type - issue a warning or build failure if type is not correct.
* @expr: the expression whose type we should check (not evaluated).
* @type: the exact type we expect the expression to be.
*
* This macro is usually used within other macros to try to ensure that a macro
* argument is of the expected type. No type promotion of the expression is
* done: an unsigned int is not the same as an int!
*
* check_type() always evaluates to 0.
*
* If your compiler does not support typeof, then the best we can do is fail
* to compile if the sizes of the types are unequal (a less complete check).
*
* Example:
* // They should always pass a 64-bit value to _set_some_value!
* #define set_some_value(expr) \
* _set_some_value((check_type((expr), uint64_t), (expr)))
*/
/**
* check_types_match - issue a warning or build failure if types are not same.
* @expr1: the first expression (not evaluated).
* @expr2: the second expression (not evaluated).
*
* This macro is usually used within other macros to try to ensure that
* arguments are of identical types. No type promotion of the expressions is
* done: an unsigned int is not the same as an int!
*
* check_types_match() always evaluates to 0.
*
* If your compiler does not support typeof, then the best we can do is fail
* to compile if the sizes of the types are unequal (a less complete check).
*
* Example:
* // Do subtraction to get to enclosing type, but make sure that
* // pointer is of correct type for that member.
* #define container_of(mbr_ptr, encl_type, mbr) \
* (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
* ((encl_type *) \
* ((char *)(mbr_ptr) - offsetof(encl_type, mbr))))
*/
#if HAVE_TYPEOF
#define check_type(expr, type) \
((typeof(expr) *)0 != (type *)0)
#define check_types_match(expr1, expr2) \
((typeof(expr1) *)0 != (typeof(expr2) *)0)
#else
#include <ccan/build_assert/build_assert.h>
/* Without typeof, we can only test the sizes. */
#define check_type(expr, type) \
BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
#define check_types_match(expr1, expr2) \
BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
#endif /* HAVE_TYPEOF */
#endif /* CCAN_CHECK_TYPE_H */

View file

@ -0,0 +1 @@
../../licenses/CC0

View file

@ -0,0 +1,65 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* container_of - routine for upcasting
*
* It is often convenient to create code where the caller registers a pointer
* to a generic structure and a callback. The callback might know that the
* pointer points to within a larger structure, and container_of gives a
* convenient and fairly type-safe way of returning to the enclosing structure.
*
* This idiom is an alternative to providing a void * pointer for every
* callback.
*
* Example:
* #include <stdio.h>
* #include <ccan/container_of/container_of.h>
*
* struct timer {
* void *members;
* };
*
* struct info {
* int my_stuff;
* struct timer timer;
* };
*
* static void my_timer_callback(struct timer *timer)
* {
* struct info *info = container_of(timer, struct info, timer);
* printf("my_stuff is %u\n", info->my_stuff);
* }
*
* static void register_timer(struct timer *timer)
* {
* (void)timer;
* (void)my_timer_callback;
* //...
* }
*
* int main(void)
* {
* struct info info = { .my_stuff = 1 };
*
* register_timer(&info.timer);
* // ...
* return 0;
* }
*
* License: CC0 (Public domain)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/check_type\n");
return 0;
}
return 1;
}

View file

@ -0,0 +1,145 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_CONTAINER_OF_H
#define CCAN_CONTAINER_OF_H
#include <stddef.h>
#include "config.h"
#include <ccan/check_type/check_type.h>
/**
* container_of - get pointer to enclosing structure
* @member_ptr: pointer to the structure member
* @containing_type: the type this member is within
* @member: the name of this member within the structure.
*
* Given a pointer to a member of a structure, this macro does pointer
* subtraction to return the pointer to the enclosing type.
*
* Example:
* struct foo {
* int fielda, fieldb;
* // ...
* };
* struct info {
* int some_other_field;
* struct foo my_foo;
* };
*
* static struct info *foo_to_info(struct foo *foo)
* {
* return container_of(foo, struct info, my_foo);
* }
*/
#define container_of(member_ptr, containing_type, member) \
((containing_type *) \
((char *)(member_ptr) \
- container_off(containing_type, member)) \
+ check_types_match(*(member_ptr), ((containing_type *)0)->member))
/**
* container_of_or_null - get pointer to enclosing structure, or NULL
* @member_ptr: pointer to the structure member
* @containing_type: the type this member is within
* @member: the name of this member within the structure.
*
* Given a pointer to a member of a structure, this macro does pointer
* subtraction to return the pointer to the enclosing type, unless it
* is given NULL, in which case it also returns NULL.
*
* Example:
* struct foo {
* int fielda, fieldb;
* // ...
* };
* struct info {
* int some_other_field;
* struct foo my_foo;
* };
*
* static struct info *foo_to_info_allowing_null(struct foo *foo)
* {
* return container_of_or_null(foo, struct info, my_foo);
* }
*/
static inline char *container_of_or_null_(void *member_ptr, size_t offset)
{
return member_ptr ? (char *)member_ptr - offset : NULL;
}
#define container_of_or_null(member_ptr, containing_type, member) \
((containing_type *) \
container_of_or_null_(member_ptr, \
container_off(containing_type, member)) \
+ check_types_match(*(member_ptr), ((containing_type *)0)->member))
/**
* container_off - get offset to enclosing structure
* @containing_type: the type this member is within
* @member: the name of this member within the structure.
*
* Given a pointer to a member of a structure, this macro does
* typechecking and figures out the offset to the enclosing type.
*
* Example:
* struct foo {
* int fielda, fieldb;
* // ...
* };
* struct info {
* int some_other_field;
* struct foo my_foo;
* };
*
* static struct info *foo_to_info(struct foo *foo)
* {
* size_t off = container_off(struct info, my_foo);
* return (void *)((char *)foo - off);
* }
*/
#define container_off(containing_type, member) \
offsetof(containing_type, member)
/**
* container_of_var - get pointer to enclosing structure using a variable
* @member_ptr: pointer to the structure member
* @container_var: a pointer of same type as this member's container
* @member: the name of this member within the structure.
*
* Given a pointer to a member of a structure, this macro does pointer
* subtraction to return the pointer to the enclosing type.
*
* Example:
* static struct info *foo_to_i(struct foo *foo)
* {
* struct info *i = container_of_var(foo, i, my_foo);
* return i;
* }
*/
#if HAVE_TYPEOF
#define container_of_var(member_ptr, container_var, member) \
container_of(member_ptr, typeof(*container_var), member)
#else
#define container_of_var(member_ptr, container_var, member) \
((void *)((char *)(member_ptr) - \
container_off_var(container_var, member)))
#endif
/**
* container_off_var - get offset of a field in enclosing structure
* @container_var: a pointer to a container structure
* @member: the name of a member within the structure.
*
* Given (any) pointer to a structure and a its member name, this
* macro does pointer subtraction to return offset of member in a
* structure memory layout.
*
*/
#if HAVE_TYPEOF
#define container_off_var(var, member) \
container_off(typeof(*var), member)
#else
#define container_off_var(var, member) \
((const char *)&(var)->member - (const char *)(var))
#endif
#endif /* CCAN_CONTAINER_OF_H */

1
ccan/ccan/endian/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../licenses/CC0

55
ccan/ccan/endian/_info Normal file
View file

@ -0,0 +1,55 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* endian - endian conversion macros for simple types
*
* Portable protocols (such as on-disk formats, or network protocols)
* are often defined to be a particular endian: little-endian (least
* significant bytes first) or big-endian (most significant bytes
* first).
*
* Similarly, some CPUs lay out values in memory in little-endian
* order (most commonly, Intel's 8086 and derivatives), or big-endian
* order (almost everyone else).
*
* This module provides conversion routines, inspired by the linux kernel.
* It also provides leint32_t, beint32_t etc typedefs, which are annotated for
* the sparse checker.
*
* Example:
* #include <stdio.h>
* #include <err.h>
* #include <ccan/endian/endian.h>
*
* //
* int main(int argc, char *argv[])
* {
* uint32_t value;
*
* if (argc != 2)
* errx(1, "Usage: %s <value>", argv[0]);
*
* value = atoi(argv[1]);
* printf("native: %08x\n", value);
* printf("little-endian: %08x\n", cpu_to_le32(value));
* printf("big-endian: %08x\n", cpu_to_be32(value));
* printf("byte-reversed: %08x\n", bswap_32(value));
* exit(0);
* }
*
* License: License: CC0 (Public domain)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0)
/* Nothing */
return 0;
return 1;
}

363
ccan/ccan/endian/endian.h Normal file
View file

@ -0,0 +1,363 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_ENDIAN_H
#define CCAN_ENDIAN_H
#include <stdint.h>
#include "config.h"
/**
* BSWAP_16 - reverse bytes in a constant uint16_t value.
* @val: constant value whose bytes to swap.
*
* Designed to be usable in constant-requiring initializers.
*
* Example:
* struct mystruct {
* char buf[BSWAP_16(0x1234)];
* };
*/
#define BSWAP_16(val) \
((((uint16_t)(val) & 0x00ff) << 8) \
| (((uint16_t)(val) & 0xff00) >> 8))
/**
* BSWAP_32 - reverse bytes in a constant uint32_t value.
* @val: constant value whose bytes to swap.
*
* Designed to be usable in constant-requiring initializers.
*
* Example:
* struct mystruct {
* char buf[BSWAP_32(0xff000000)];
* };
*/
#define BSWAP_32(val) \
((((uint32_t)(val) & 0x000000ff) << 24) \
| (((uint32_t)(val) & 0x0000ff00) << 8) \
| (((uint32_t)(val) & 0x00ff0000) >> 8) \
| (((uint32_t)(val) & 0xff000000) >> 24))
/**
* BSWAP_64 - reverse bytes in a constant uint64_t value.
* @val: constantvalue whose bytes to swap.
*
* Designed to be usable in constant-requiring initializers.
*
* Example:
* struct mystruct {
* char buf[BSWAP_64(0xff00000000000000ULL)];
* };
*/
#define BSWAP_64(val) \
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
#if HAVE_BYTESWAP_H
#include <byteswap.h>
#else
/**
* bswap_16 - reverse bytes in a uint16_t value.
* @val: value whose bytes to swap.
*
* Example:
* // Output contains "1024 is 4 as two bytes reversed"
* printf("1024 is %u as two bytes reversed\n", bswap_16(1024));
*/
static inline uint16_t bswap_16(uint16_t val)
{
return BSWAP_16(val);
}
/**
* bswap_32 - reverse bytes in a uint32_t value.
* @val: value whose bytes to swap.
*
* Example:
* // Output contains "1024 is 262144 as four bytes reversed"
* printf("1024 is %u as four bytes reversed\n", bswap_32(1024));
*/
static inline uint32_t bswap_32(uint32_t val)
{
return BSWAP_32(val);
}
#endif /* !HAVE_BYTESWAP_H */
#if !HAVE_BSWAP_64
/**
* bswap_64 - reverse bytes in a uint64_t value.
* @val: value whose bytes to swap.
*
* Example:
* // Output contains "1024 is 1125899906842624 as eight bytes reversed"
* printf("1024 is %llu as eight bytes reversed\n",
* (unsigned long long)bswap_64(1024));
*/
static inline uint64_t bswap_64(uint64_t val)
{
return BSWAP_64(val);
}
#endif
/* Needed for Glibc like endiness check */
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
/* Sanity check the defines. We don't handle weird endianness. */
#if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN
#error "Unknown endian"
#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN
#error "Can't compile for both big and little endian."
#elif HAVE_LITTLE_ENDIAN
#ifndef __BYTE_ORDER
#define __BYTE_ORDER __LITTLE_ENDIAN
#elif __BYTE_ORDER != __LITTLE_ENDIAN
#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN"
#endif
#elif HAVE_BIG_ENDIAN
#ifndef __BYTE_ORDER
#define __BYTE_ORDER __BIG_ENDIAN
#elif __BYTE_ORDER != __BIG_ENDIAN
#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN"
#endif
#endif
#ifdef __CHECKER__
/* sparse needs forcing to remove bitwise attribute from ccan/short_types */
#define ENDIAN_CAST __attribute__((force))
#define ENDIAN_TYPE __attribute__((bitwise))
#else
#define ENDIAN_CAST
#define ENDIAN_TYPE
#endif
typedef uint64_t ENDIAN_TYPE leint64_t;
typedef uint64_t ENDIAN_TYPE beint64_t;
typedef uint32_t ENDIAN_TYPE leint32_t;
typedef uint32_t ENDIAN_TYPE beint32_t;
typedef uint16_t ENDIAN_TYPE leint16_t;
typedef uint16_t ENDIAN_TYPE beint16_t;
#if HAVE_LITTLE_ENDIAN
/**
* CPU_TO_LE64 - convert a constant uint64_t value to little-endian
* @native: constant to convert
*/
#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native))
/**
* CPU_TO_LE32 - convert a constant uint32_t value to little-endian
* @native: constant to convert
*/
#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native))
/**
* CPU_TO_LE16 - convert a constant uint16_t value to little-endian
* @native: constant to convert
*/
#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native))
/**
* LE64_TO_CPU - convert a little-endian uint64_t constant
* @le_val: little-endian constant to convert
*/
#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val))
/**
* LE32_TO_CPU - convert a little-endian uint32_t constant
* @le_val: little-endian constant to convert
*/
#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val))
/**
* LE16_TO_CPU - convert a little-endian uint16_t constant
* @le_val: little-endian constant to convert
*/
#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
#else /* ... HAVE_BIG_ENDIAN */
#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native))
#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native))
#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native))
#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val)
#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val)
#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val)
#endif /* HAVE_BIG_ENDIAN */
#if HAVE_BIG_ENDIAN
/**
* CPU_TO_BE64 - convert a constant uint64_t value to big-endian
* @native: constant to convert
*/
#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native))
/**
* CPU_TO_BE32 - convert a constant uint32_t value to big-endian
* @native: constant to convert
*/
#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native))
/**
* CPU_TO_BE16 - convert a constant uint16_t value to big-endian
* @native: constant to convert
*/
#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native))
/**
* BE64_TO_CPU - convert a big-endian uint64_t constant
* @le_val: big-endian constant to convert
*/
#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val))
/**
* BE32_TO_CPU - convert a big-endian uint32_t constant
* @le_val: big-endian constant to convert
*/
#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val))
/**
* BE16_TO_CPU - convert a big-endian uint16_t constant
* @le_val: big-endian constant to convert
*/
#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
#else /* ... HAVE_LITTLE_ENDIAN */
#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native))
#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native))
#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native))
#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val)
#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val)
#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val)
#endif /* HAVE_LITTE_ENDIAN */
/**
* cpu_to_le64 - convert a uint64_t value to little-endian
* @native: value to convert
*/
static inline leint64_t cpu_to_le64(uint64_t native)
{
return CPU_TO_LE64(native);
}
/**
* cpu_to_le32 - convert a uint32_t value to little-endian
* @native: value to convert
*/
static inline leint32_t cpu_to_le32(uint32_t native)
{
return CPU_TO_LE32(native);
}
/**
* cpu_to_le16 - convert a uint16_t value to little-endian
* @native: value to convert
*/
static inline leint16_t cpu_to_le16(uint16_t native)
{
return CPU_TO_LE16(native);
}
/**
* le64_to_cpu - convert a little-endian uint64_t value
* @le_val: little-endian value to convert
*/
static inline uint64_t le64_to_cpu(leint64_t le_val)
{
return LE64_TO_CPU(le_val);
}
/**
* le32_to_cpu - convert a little-endian uint32_t value
* @le_val: little-endian value to convert
*/
static inline uint32_t le32_to_cpu(leint32_t le_val)
{
return LE32_TO_CPU(le_val);
}
/**
* le16_to_cpu - convert a little-endian uint16_t value
* @le_val: little-endian value to convert
*/
static inline uint16_t le16_to_cpu(leint16_t le_val)
{
return LE16_TO_CPU(le_val);
}
/**
* cpu_to_be64 - convert a uint64_t value to big endian.
* @native: value to convert
*/
static inline beint64_t cpu_to_be64(uint64_t native)
{
return CPU_TO_BE64(native);
}
/**
* cpu_to_be32 - convert a uint32_t value to big endian.
* @native: value to convert
*/
static inline beint32_t cpu_to_be32(uint32_t native)
{
return CPU_TO_BE32(native);
}
/**
* cpu_to_be16 - convert a uint16_t value to big endian.
* @native: value to convert
*/
static inline beint16_t cpu_to_be16(uint16_t native)
{
return CPU_TO_BE16(native);
}
/**
* be64_to_cpu - convert a big-endian uint64_t value
* @be_val: big-endian value to convert
*/
static inline uint64_t be64_to_cpu(beint64_t be_val)
{
return BE64_TO_CPU(be_val);
}
/**
* be32_to_cpu - convert a big-endian uint32_t value
* @be_val: big-endian value to convert
*/
static inline uint32_t be32_to_cpu(beint32_t be_val)
{
return BE32_TO_CPU(be_val);
}
/**
* be16_to_cpu - convert a big-endian uint16_t value
* @be_val: big-endian value to convert
*/
static inline uint16_t be16_to_cpu(beint16_t be_val)
{
return BE16_TO_CPU(be_val);
}
/* Whichever they include first, they get these definitions. */
#ifdef CCAN_SHORT_TYPES_H
/**
* be64/be32/be16 - 64/32/16 bit big-endian representation.
*/
typedef beint64_t be64;
typedef beint32_t be32;
typedef beint16_t be16;
/**
* le64/le32/le16 - 64/32/16 bit little-endian representation.
*/
typedef leint64_t le64;
typedef leint32_t le32;
typedef leint16_t le16;
#endif
#endif /* CCAN_ENDIAN_H */

1
ccan/ccan/list/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../licenses/BSD-MIT

72
ccan/ccan/list/_info Normal file
View file

@ -0,0 +1,72 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* list - double linked list routines
*
* The list header contains routines for manipulating double linked lists.
* It defines two types: struct list_head used for anchoring lists, and
* struct list_node which is usually embedded in the structure which is placed
* in the list.
*
* Example:
* #include <err.h>
* #include <stdio.h>
* #include <stdlib.h>
* #include <ccan/list/list.h>
*
* struct parent {
* const char *name;
* struct list_head children;
* unsigned int num_children;
* };
*
* struct child {
* const char *name;
* struct list_node list;
* };
*
* int main(int argc, char *argv[])
* {
* struct parent p;
* struct child *c;
* int i;
*
* if (argc < 2)
* errx(1, "Usage: %s parent children...", argv[0]);
*
* p.name = argv[1];
* list_head_init(&p.children);
* p.num_children = 0;
* for (i = 2; i < argc; i++) {
* c = malloc(sizeof(*c));
* c->name = argv[i];
* list_add(&p.children, &c->list);
* p.num_children++;
* }
*
* printf("%s has %u children:", p.name, p.num_children);
* list_for_each(&p.children, c, list)
* printf("%s ", c->name);
* printf("\n");
* return 0;
* }
*
* License: BSD-MIT
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/str\n");
printf("ccan/container_of\n");
printf("ccan/check_type\n");
return 0;
}
return 1;
}

43
ccan/ccan/list/list.c Normal file
View file

@ -0,0 +1,43 @@
/* Licensed under BSD-MIT - see LICENSE file for details */
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
static void *corrupt(const char *abortstr,
const struct list_node *head,
const struct list_node *node,
unsigned int count)
{
if (abortstr) {
fprintf(stderr,
"%s: prev corrupt in node %p (%u) of %p\n",
abortstr, node, count, head);
abort();
}
return NULL;
}
struct list_node *list_check_node(const struct list_node *node,
const char *abortstr)
{
const struct list_node *p, *n;
int count = 0;
for (p = node, n = node->next; n != node; p = n, n = n->next) {
count++;
if (n->prev != p)
return corrupt(abortstr, node, n, count);
}
/* Check prev on head node. */
if (node->prev != p)
return corrupt(abortstr, node, node, 0);
return (struct list_node *)node;
}
struct list_head *list_check(const struct list_head *h, const char *abortstr)
{
if (!list_check_node(&h->n, abortstr))
return NULL;
return (struct list_head *)h;
}

842
ccan/ccan/list/list.h Normal file
View file

@ -0,0 +1,842 @@
/* Licensed under BSD-MIT - see LICENSE file for details */
#ifndef CCAN_LIST_H
#define CCAN_LIST_H
//#define CCAN_LIST_DEBUG 1
#include <stdbool.h>
#include <assert.h>
#include <ccan/str/str.h>
#include <ccan/container_of/container_of.h>
#include <ccan/check_type/check_type.h>
/**
* struct list_node - an entry in a doubly-linked list
* @next: next entry (self if empty)
* @prev: previous entry (self if empty)
*
* This is used as an entry in a linked list.
* Example:
* struct child {
* const char *name;
* // Linked list of all us children.
* struct list_node list;
* };
*/
struct list_node
{
struct list_node *next, *prev;
};
/**
* struct list_head - the head of a doubly-linked list
* @h: the list_head (containing next and prev pointers)
*
* This is used as the head of a linked list.
* Example:
* struct parent {
* const char *name;
* struct list_head children;
* unsigned int num_children;
* };
*/
struct list_head
{
struct list_node n;
};
/**
* list_check - check head of a list for consistency
* @h: the list_head
* @abortstr: the location to print on aborting, or NULL.
*
* Because list_nodes have redundant information, consistency checking between
* the back and forward links can be done. This is useful as a debugging check.
* If @abortstr is non-NULL, that will be printed in a diagnostic if the list
* is inconsistent, and the function will abort.
*
* Returns the list head if the list is consistent, NULL if not (it
* can never return NULL if @abortstr is set).
*
* See also: list_check_node()
*
* Example:
* static void dump_parent(struct parent *p)
* {
* struct child *c;
*
* printf("%s (%u children):\n", p->name, p->num_children);
* list_check(&p->children, "bad child list");
* list_for_each(&p->children, c, list)
* printf(" -> %s\n", c->name);
* }
*/
struct list_head *list_check(const struct list_head *h, const char *abortstr);
/**
* list_check_node - check node of a list for consistency
* @n: the list_node
* @abortstr: the location to print on aborting, or NULL.
*
* Check consistency of the list node is in (it must be in one).
*
* See also: list_check()
*
* Example:
* static void dump_child(const struct child *c)
* {
* list_check_node(&c->list, "bad child list");
* printf("%s\n", c->name);
* }
*/
struct list_node *list_check_node(const struct list_node *n,
const char *abortstr);
#define LIST_LOC __FILE__ ":" stringify(__LINE__)
#ifdef CCAN_LIST_DEBUG
#define list_debug(h, loc) list_check((h), loc)
#define list_debug_node(n, loc) list_check_node((n), loc)
#else
#define list_debug(h, loc) ((void)loc, h)
#define list_debug_node(n, loc) ((void)loc, n)
#endif
/**
* LIST_HEAD_INIT - initializer for an empty list_head
* @name: the name of the list.
*
* Explicit initializer for an empty list.
*
* See also:
* LIST_HEAD, list_head_init()
*
* Example:
* static struct list_head my_list = LIST_HEAD_INIT(my_list);
*/
#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } }
/**
* LIST_HEAD - define and initialize an empty list_head
* @name: the name of the list.
*
* The LIST_HEAD macro defines a list_head and initializes it to an empty
* list. It can be prepended by "static" to define a static list_head.
*
* See also:
* LIST_HEAD_INIT, list_head_init()
*
* Example:
* static LIST_HEAD(my_global_list);
*/
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
/**
* list_head_init - initialize a list_head
* @h: the list_head to set to the empty list
*
* Example:
* ...
* struct parent *parent = malloc(sizeof(*parent));
*
* list_head_init(&parent->children);
* parent->num_children = 0;
*/
static inline void list_head_init(struct list_head *h)
{
h->n.next = h->n.prev = &h->n;
}
/**
* list_node_init - initialize a list_node
* @n: the list_node to link to itself.
*
* You don't need to use this normally! But it lets you list_del(@n)
* safely.
*/
static inline void list_node_init(struct list_node *n)
{
n->next = n->prev = n;
}
/**
* list_add_after - add an entry after an existing node in a linked list
* @h: the list_head to add the node to (for debugging)
* @p: the existing list_node to add the node after
* @n: the new list_node to add to the list.
*
* The existing list_node must already be a member of the list.
* The new list_node does not need to be initialized; it will be overwritten.
*
* Example:
* struct child c1, c2, c3;
* LIST_HEAD(h);
*
* list_add_tail(&h, &c1.list);
* list_add_tail(&h, &c3.list);
* list_add_after(&h, &c1.list, &c2.list);
*/
#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC)
static inline void list_add_after_(struct list_head *h,
struct list_node *p,
struct list_node *n,
const char *abortstr)
{
n->next = p->next;
n->prev = p;
p->next->prev = n;
p->next = n;
(void)list_debug(h, abortstr);
}
/**
* list_add - add an entry at the start of a linked list.
* @h: the list_head to add the node to
* @n: the list_node to add to the list.
*
* The list_node does not need to be initialized; it will be overwritten.
* Example:
* struct child *child = malloc(sizeof(*child));
*
* child->name = "marvin";
* list_add(&parent->children, &child->list);
* parent->num_children++;
*/
#define list_add(h, n) list_add_(h, n, LIST_LOC)
static inline void list_add_(struct list_head *h,
struct list_node *n,
const char *abortstr)
{
list_add_after_(h, &h->n, n, abortstr);
}
/**
* list_add_before - add an entry before an existing node in a linked list
* @h: the list_head to add the node to (for debugging)
* @p: the existing list_node to add the node before
* @n: the new list_node to add to the list.
*
* The existing list_node must already be a member of the list.
* The new list_node does not need to be initialized; it will be overwritten.
*
* Example:
* list_head_init(&h);
* list_add_tail(&h, &c1.list);
* list_add_tail(&h, &c3.list);
* list_add_before(&h, &c3.list, &c2.list);
*/
#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC)
static inline void list_add_before_(struct list_head *h,
struct list_node *p,
struct list_node *n,
const char *abortstr)
{
n->next = p;
n->prev = p->prev;
p->prev->next = n;
p->prev = n;
(void)list_debug(h, abortstr);
}
/**
* list_add_tail - add an entry at the end of a linked list.
* @h: the list_head to add the node to
* @n: the list_node to add to the list.
*
* The list_node does not need to be initialized; it will be overwritten.
* Example:
* list_add_tail(&parent->children, &child->list);
* parent->num_children++;
*/
#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC)
static inline void list_add_tail_(struct list_head *h,
struct list_node *n,
const char *abortstr)
{
list_add_before_(h, &h->n, n, abortstr);
}
/**
* list_empty - is a list empty?
* @h: the list_head
*
* If the list is empty, returns true.
*
* Example:
* assert(list_empty(&parent->children) == (parent->num_children == 0));
*/
#define list_empty(h) list_empty_(h, LIST_LOC)
static inline bool list_empty_(const struct list_head *h, const char* abortstr)
{
(void)list_debug(h, abortstr);
return h->n.next == &h->n;
}
/**
* list_empty_nodebug - is a list empty (and don't perform debug checks)?
* @h: the list_head
*
* If the list is empty, returns true.
* This differs from list_empty() in that if CCAN_LIST_DEBUG is set it
* will NOT perform debug checks. Only use this function if you REALLY
* know what you're doing.
*
* Example:
* assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0));
*/
#ifndef CCAN_LIST_DEBUG
#define list_empty_nodebug(h) list_empty(h)
#else
static inline bool list_empty_nodebug(const struct list_head *h)
{
return h->n.next == &h->n;
}
#endif
/**
* list_empty_nocheck - is a list empty?
* @h: the list_head
*
* If the list is empty, returns true. This doesn't perform any
* debug check for list consistency, so it can be called without
* locks, racing with the list being modified. This is ok for
* checks where an incorrect result is not an issue (optimized
* bail out path for example).
*/
static inline bool list_empty_nocheck(const struct list_head *h)
{
return h->n.next == &h->n;
}
/**
* list_del - delete an entry from an (unknown) linked list.
* @n: the list_node to delete from the list.
*
* Note that this leaves @n in an undefined state; it can be added to
* another list, but not deleted again.
*
* See also:
* list_del_from(), list_del_init()
*
* Example:
* list_del(&child->list);
* parent->num_children--;
*/
#define list_del(n) list_del_(n, LIST_LOC)
static inline void list_del_(struct list_node *n, const char* abortstr)
{
(void)list_debug_node(n, abortstr);
n->next->prev = n->prev;
n->prev->next = n->next;
#ifdef CCAN_LIST_DEBUG
/* Catch use-after-del. */
n->next = n->prev = NULL;
#endif
}
/**
* list_del_init - delete a node, and reset it so it can be deleted again.
* @n: the list_node to be deleted.
*
* list_del(@n) or list_del_init() again after this will be safe,
* which can be useful in some cases.
*
* See also:
* list_del_from(), list_del()
*
* Example:
* list_del_init(&child->list);
* parent->num_children--;
*/
#define list_del_init(n) list_del_init_(n, LIST_LOC)
static inline void list_del_init_(struct list_node *n, const char *abortstr)
{
list_del_(n, abortstr);
list_node_init(n);
}
/**
* list_del_from - delete an entry from a known linked list.
* @h: the list_head the node is in.
* @n: the list_node to delete from the list.
*
* This explicitly indicates which list a node is expected to be in,
* which is better documentation and can catch more bugs.
*
* See also: list_del()
*
* Example:
* list_del_from(&parent->children, &child->list);
* parent->num_children--;
*/
static inline void list_del_from(struct list_head *h, struct list_node *n)
{
#ifdef CCAN_LIST_DEBUG
{
/* Thorough check: make sure it was in list! */
struct list_node *i;
for (i = h->n.next; i != n; i = i->next)
assert(i != &h->n);
}
#endif /* CCAN_LIST_DEBUG */
/* Quick test that catches a surprising number of bugs. */
assert(!list_empty(h));
list_del(n);
}
/**
* list_swap - swap out an entry from an (unknown) linked list for a new one.
* @o: the list_node to replace from the list.
* @n: the list_node to insert in place of the old one.
*
* Note that this leaves @o in an undefined state; it can be added to
* another list, but not deleted/swapped again.
*
* See also:
* list_del()
*
* Example:
* struct child x1, x2;
* LIST_HEAD(xh);
*
* list_add(&xh, &x1.list);
* list_swap(&x1.list, &x2.list);
*/
#define list_swap(o, n) list_swap_(o, n, LIST_LOC)
static inline void list_swap_(struct list_node *o,
struct list_node *n,
const char* abortstr)
{
(void)list_debug_node(o, abortstr);
*n = *o;
n->next->prev = n;
n->prev->next = n;
#ifdef CCAN_LIST_DEBUG
/* Catch use-after-del. */
o->next = o->prev = NULL;
#endif
}
/**
* list_entry - convert a list_node back into the structure containing it.
* @n: the list_node
* @type: the type of the entry
* @member: the list_node member of the type
*
* Example:
* // First list entry is children.next; convert back to child.
* child = list_entry(parent->children.n.next, struct child, list);
*
* See Also:
* list_top(), list_for_each()
*/
#define list_entry(n, type, member) container_of(n, type, member)
/**
* list_top - get the first entry in a list
* @h: the list_head
* @type: the type of the entry
* @member: the list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *first;
* first = list_top(&parent->children, struct child, list);
* if (!first)
* printf("Empty list!\n");
*/
#define list_top(h, type, member) \
((type *)list_top_((h), list_off_(type, member)))
static inline const void *list_top_(const struct list_head *h, size_t off)
{
if (list_empty(h))
return NULL;
return (const char *)h->n.next - off;
}
/**
* list_pop - remove the first entry in a list
* @h: the list_head
* @type: the type of the entry
* @member: the list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *one;
* one = list_pop(&parent->children, struct child, list);
* if (!one)
* printf("Empty list!\n");
*/
#define list_pop(h, type, member) \
((type *)list_pop_((h), list_off_(type, member)))
static inline const void *list_pop_(const struct list_head *h, size_t off)
{
struct list_node *n;
if (list_empty(h))
return NULL;
n = h->n.next;
list_del(n);
return (const char *)n - off;
}
/**
* list_tail - get the last entry in a list
* @h: the list_head
* @type: the type of the entry
* @member: the list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *last;
* last = list_tail(&parent->children, struct child, list);
* if (!last)
* printf("Empty list!\n");
*/
#define list_tail(h, type, member) \
((type *)list_tail_((h), list_off_(type, member)))
static inline const void *list_tail_(const struct list_head *h, size_t off)
{
if (list_empty(h))
return NULL;
return (const char *)h->n.prev - off;
}
/**
* list_for_each - iterate through a list.
* @h: the list_head (warning: evaluated multiple times!)
* @i: the structure containing the list_node
* @member: the list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list. It's
* a for loop, so you can break and continue as normal.
*
* Example:
* list_for_each(&parent->children, child, list)
* printf("Name: %s\n", child->name);
*/
#define list_for_each(h, i, member) \
list_for_each_off(h, i, list_off_var_(i, member))
/**
* list_for_each_rev - iterate through a list backwards.
* @h: the list_head
* @i: the structure containing the list_node
* @member: the list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list. It's
* a for loop, so you can break and continue as normal.
*
* Example:
* list_for_each_rev(&parent->children, child, list)
* printf("Name: %s\n", child->name);
*/
#define list_for_each_rev(h, i, member) \
list_for_each_rev_off(h, i, list_off_var_(i, member))
/**
* list_for_each_rev_safe - iterate through a list backwards,
* maybe during deletion
* @h: the list_head
* @i: the structure containing the list_node
* @nxt: the structure containing the list_node
* @member: the list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list backwards.
* It's a for loop, so you can break and continue as normal. The extra
* variable * @nxt is used to hold the next element, so you can delete @i
* from the list.
*
* Example:
* struct child *next;
* list_for_each_rev_safe(&parent->children, child, next, list) {
* printf("Name: %s\n", child->name);
* }
*/
#define list_for_each_rev_safe(h, i, nxt, member) \
list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member))
/**
* list_for_each_safe - iterate through a list, maybe during deletion
* @h: the list_head
* @i: the structure containing the list_node
* @nxt: the structure containing the list_node
* @member: the list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list. It's
* a for loop, so you can break and continue as normal. The extra variable
* @nxt is used to hold the next element, so you can delete @i from the list.
*
* Example:
* list_for_each_safe(&parent->children, child, next, list) {
* list_del(&child->list);
* parent->num_children--;
* }
*/
#define list_for_each_safe(h, i, nxt, member) \
list_for_each_safe_off(h, i, nxt, list_off_var_(i, member))
/**
* list_next - get the next entry in a list
* @h: the list_head
* @i: a pointer to an entry in the list.
* @member: the list_node member of the structure
*
* If @i was the last entry in the list, returns NULL.
*
* Example:
* struct child *second;
* second = list_next(&parent->children, first, list);
* if (!second)
* printf("No second child!\n");
*/
#define list_next(h, i, member) \
((list_typeof(i))list_entry_or_null(list_debug(h, \
__FILE__ ":" stringify(__LINE__)), \
(i)->member.next, \
list_off_var_((i), member)))
/**
* list_prev - get the previous entry in a list
* @h: the list_head
* @i: a pointer to an entry in the list.
* @member: the list_node member of the structure
*
* If @i was the first entry in the list, returns NULL.
*
* Example:
* first = list_prev(&parent->children, second, list);
* if (!first)
* printf("Can't go back to first child?!\n");
*/
#define list_prev(h, i, member) \
((list_typeof(i))list_entry_or_null(list_debug(h, \
__FILE__ ":" stringify(__LINE__)), \
(i)->member.prev, \
list_off_var_((i), member)))
/**
* list_append_list - empty one list onto the end of another.
* @to: the list to append into
* @from: the list to empty.
*
* This takes the entire contents of @from and moves it to the end of
* @to. After this @from will be empty.
*
* Example:
* struct list_head adopter;
*
* list_append_list(&adopter, &parent->children);
* assert(list_empty(&parent->children));
* parent->num_children = 0;
*/
#define list_append_list(t, f) list_append_list_(t, f, \
__FILE__ ":" stringify(__LINE__))
static inline void list_append_list_(struct list_head *to,
struct list_head *from,
const char *abortstr)
{
struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
struct list_node *to_tail = list_debug(to, abortstr)->n.prev;
/* Sew in head and entire list. */
to->n.prev = from_tail;
from_tail->next = &to->n;
to_tail->next = &from->n;
from->n.prev = to_tail;
/* Now remove head. */
list_del(&from->n);
list_head_init(from);
}
/**
* list_prepend_list - empty one list into the start of another.
* @to: the list to prepend into
* @from: the list to empty.
*
* This takes the entire contents of @from and moves it to the start
* of @to. After this @from will be empty.
*
* Example:
* list_prepend_list(&adopter, &parent->children);
* assert(list_empty(&parent->children));
* parent->num_children = 0;
*/
#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC)
static inline void list_prepend_list_(struct list_head *to,
struct list_head *from,
const char *abortstr)
{
struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
struct list_node *to_head = list_debug(to, abortstr)->n.next;
/* Sew in head and entire list. */
to->n.next = &from->n;
from->n.prev = &to->n;
to_head->prev = from_tail;
from_tail->next = to_head;
/* Now remove head. */
list_del(&from->n);
list_head_init(from);
}
/* internal macros, do not use directly */
#define list_for_each_off_dir_(h, i, off, dir) \
for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \
(off)); \
list_node_from_off_((void *)i, (off)) != &(h)->n; \
i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \
(off)))
#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \
for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \
(off)), \
nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \
(off)); \
list_node_from_off_(i, (off)) != &(h)->n; \
i = nxt, \
nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \
(off)))
/**
* list_for_each_off - iterate through a list of memory regions.
* @h: the list_head
* @i: the pointer to a memory region which contains list node data.
* @off: offset(relative to @i) at which list node data resides.
*
* This is a low-level wrapper to iterate @i over the entire list, used to
* implement all oher, more high-level, for-each constructs. It's a for loop,
* so you can break and continue as normal.
*
* WARNING! Being the low-level macro that it is, this wrapper doesn't know
* nor care about the type of @i. The only assumption made is that @i points
* to a chunk of memory that at some @offset, relative to @i, contains a
* properly filled `struct list_node' which in turn contains pointers to
* memory chunks and it's turtles all the way down. With all that in mind
* remember that given the wrong pointer/offset couple this macro will
* happily churn all you memory until SEGFAULT stops it, in other words
* caveat emptor.
*
* It is worth mentioning that one of legitimate use-cases for that wrapper
* is operation on opaque types with known offset for `struct list_node'
* member(preferably 0), because it allows you not to disclose the type of
* @i.
*
* Example:
* list_for_each_off(&parent->children, child,
* offsetof(struct child, list))
* printf("Name: %s\n", child->name);
*/
#define list_for_each_off(h, i, off) \
list_for_each_off_dir_((h),(i),(off),next)
/**
* list_for_each_rev_off - iterate through a list of memory regions backwards
* @h: the list_head
* @i: the pointer to a memory region which contains list node data.
* @off: offset(relative to @i) at which list node data resides.
*
* See list_for_each_off for details
*/
#define list_for_each_rev_off(h, i, off) \
list_for_each_off_dir_((h),(i),(off),prev)
/**
* list_for_each_safe_off - iterate through a list of memory regions, maybe
* during deletion
* @h: the list_head
* @i: the pointer to a memory region which contains list node data.
* @nxt: the structure containing the list_node
* @off: offset(relative to @i) at which list node data resides.
*
* For details see `list_for_each_off' and `list_for_each_safe'
* descriptions.
*
* Example:
* list_for_each_safe_off(&parent->children, child,
* next, offsetof(struct child, list))
* printf("Name: %s\n", child->name);
*/
#define list_for_each_safe_off(h, i, nxt, off) \
list_for_each_safe_off_dir_((h),(i),(nxt),(off),next)
/**
* list_for_each_rev_safe_off - iterate backwards through a list of
* memory regions, maybe during deletion
* @h: the list_head
* @i: the pointer to a memory region which contains list node data.
* @nxt: the structure containing the list_node
* @off: offset(relative to @i) at which list node data resides.
*
* For details see `list_for_each_rev_off' and `list_for_each_rev_safe'
* descriptions.
*
* Example:
* list_for_each_rev_safe_off(&parent->children, child,
* next, offsetof(struct child, list))
* printf("Name: %s\n", child->name);
*/
#define list_for_each_rev_safe_off(h, i, nxt, off) \
list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev)
/* Other -off variants. */
#define list_entry_off(n, type, off) \
((type *)list_node_from_off_((n), (off)))
#define list_head_off(h, type, off) \
((type *)list_head_off((h), (off)))
#define list_tail_off(h, type, off) \
((type *)list_tail_((h), (off)))
#define list_add_off(h, n, off) \
list_add((h), list_node_from_off_((n), (off)))
#define list_del_off(n, off) \
list_del(list_node_from_off_((n), (off)))
#define list_del_from_off(h, n, off) \
list_del_from(h, list_node_from_off_((n), (off)))
/* Offset helper functions so we only single-evaluate. */
static inline void *list_node_to_off_(struct list_node *node, size_t off)
{
return (void *)((char *)node - off);
}
static inline struct list_node *list_node_from_off_(void *ptr, size_t off)
{
return (struct list_node *)((char *)ptr + off);
}
/* Get the offset of the member, but make sure it's a list_node. */
#define list_off_(type, member) \
(container_off(type, member) + \
check_type(((type *)0)->member, struct list_node))
#define list_off_var_(var, member) \
(container_off_var(var, member) + \
check_type(var->member, struct list_node))
#if HAVE_TYPEOF
#define list_typeof(var) typeof(var)
#else
#define list_typeof(var) void *
#endif
/* Returns member, or NULL if at end of list. */
static inline void *list_entry_or_null(const struct list_head *h,
const struct list_node *n,
size_t off)
{
if (n == &h->n)
return NULL;
return (char *)n - off;
}
#endif /* CCAN_LIST_H */

1
ccan/ccan/minmax/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../licenses/CC0

48
ccan/ccan/minmax/_info Normal file
View file

@ -0,0 +1,48 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* minmax - typesafe minimum and maximum functions
*
* The classic implementation of minimum / maximum macros in C can be
* very dangerous. If the two arguments have different sizes, or
* different signedness, type promotion rules can lead to very
* surprising results.
*
* This module implements typesafe versions, which will generate a
* compile time error, if the arguments have different types.
*
* Example:
* #include <ccan/minmax/minmax.h>
* #include <stdio.h>
*
* int main(int argc, char *argv[])
* {
* printf("Signed max: %d\n", max(1, -1));
* printf("Unsigned max: %u\n", max(1U, -1U));
* return 0;
* }
*
* Author: David Gibson <david@gibson.dropbear.id.au>
* License: CC0 (Public domain)
*/
int main(int argc, char *argv[])
{
/* Expect exactly one argument */
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
return 0;
}
if (strcmp(argv[1], "ccanlint") == 0) {
/* We need several gcc extensions */
printf("tests_compile_without_features FAIL\n");
return 0;
}
return 1;
}

65
ccan/ccan/minmax/minmax.h Normal file
View file

@ -0,0 +1,65 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_MINMAX_H
#define CCAN_MINMAX_H
#include "config.h"
#include <ccan/build_assert/build_assert.h>
#if !HAVE_STATEMENT_EXPR || !HAVE_TYPEOF
/*
* Without these, there's no way to avoid unsafe double evaluation of
* the arguments
*/
#error Sorry, minmax module requires statement expressions and typeof
#endif
#if HAVE_BUILTIN_TYPES_COMPATIBLE_P
#define MINMAX_ASSERT_COMPATIBLE(a, b) \
BUILD_ASSERT(__builtin_types_compatible_p(a, b))
#else
#define MINMAX_ASSERT_COMPATIBLE(a, b) \
do { } while (0)
#endif
#define min(a, b) \
({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
MINMAX_ASSERT_COMPATIBLE(typeof(_a), typeof(_b)); \
_a < _b ? _a : _b; \
})
#define max(a, b) \
({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
MINMAX_ASSERT_COMPATIBLE(typeof(_a), typeof(_b)); \
_a > _b ? _a : _b; \
})
#define clamp(v, f, c) (max(min((v), (c)), (f)))
#define min_t(t, a, b) \
({ \
t _ta = (a); \
t _tb = (b); \
min(_ta, _tb); \
})
#define max_t(t, a, b) \
({ \
t _ta = (a); \
t _tb = (b); \
max(_ta, _tb); \
})
#define clamp_t(t, v, f, c) \
({ \
t _tv = (v); \
t _tf = (f); \
t _tc = (c); \
clamp(_tv, _tf, _tc); \
})
#endif /* CCAN_MINMAX_H */

View file

@ -0,0 +1 @@
../../licenses/CC0

View file

@ -0,0 +1,35 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_SHORT_TYPES_H
#define CCAN_SHORT_TYPES_H
#include <stdint.h>
/**
* u64/s64/u32/s32/u16/s16/u8/s8 - short names for explicitly-sized types.
*/
typedef uint64_t u64;
typedef int64_t s64;
typedef uint32_t u32;
typedef int32_t s32;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint8_t u8;
typedef int8_t s8;
/* Whichever they include first, they get these definitions. */
#ifdef CCAN_ENDIAN_H
/**
* be64/be32/be16 - 64/32/16 bit big-endian representation.
*/
typedef beint64_t be64;
typedef beint32_t be32;
typedef beint16_t be16;
/**
* le64/le32/le16 - 64/32/16 bit little-endian representation.
*/
typedef leint64_t le64;
typedef leint32_t le32;
typedef leint16_t le16;
#endif
#endif /* CCAN_SHORT_TYPES_H */

1
ccan/ccan/str/LICENSE Symbolic link
View file

@ -0,0 +1 @@
../../licenses/CC0

52
ccan/ccan/str/_info Normal file
View file

@ -0,0 +1,52 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
/**
* str - string helper routines
*
* This is a grab bag of functions for string operations, designed to enhance
* the standard string.h.
*
* Note that if you define CCAN_STR_DEBUG, you will get extra compile
* checks on common misuses of the following functions (they will now
* be out-of-line, so there is a runtime penalty!).
*
* strstr, strchr, strrchr:
* Return const char * if first argument is const (gcc only).
*
* isalnum, isalpha, isascii, isblank, iscntrl, isdigit, isgraph,
* islower, isprint, ispunct, isspace, isupper, isxdigit:
* Static and runtime check that input is EOF or an *unsigned*
* char, as per C standard (really!).
*
* Example:
* #include <stdio.h>
* #include <ccan/str/str.h>
*
* int main(int argc, char *argv[])
* {
* if (argc > 1 && streq(argv[1], "--verbose"))
* printf("verbose set\n");
* if (argc > 1 && strstarts(argv[1], "--"))
* printf("Some option set\n");
* if (argc > 1 && strends(argv[1], "cow-powers"))
* printf("Magic option set\n");
* return 0;
* }
*
* License: CC0 (Public domain)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
return 0;
}
return 1;
}

108
ccan/ccan/str/debug.c Normal file
View file

@ -0,0 +1,108 @@
/* CC0 (Public domain) - see LICENSE file for details */
#include "config.h"
#include <ccan/str/str_debug.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
#ifdef CCAN_STR_DEBUG
/* Because we mug the real ones with macros, we need our own wrappers. */
int str_isalnum(int i)
{
assert(i >= -1 && i < 256);
return isalnum(i);
}
int str_isalpha(int i)
{
assert(i >= -1 && i < 256);
return isalpha(i);
}
int str_isascii(int i)
{
assert(i >= -1 && i < 256);
return isascii(i);
}
#if HAVE_ISBLANK
int str_isblank(int i)
{
assert(i >= -1 && i < 256);
return isblank(i);
}
#endif
int str_iscntrl(int i)
{
assert(i >= -1 && i < 256);
return iscntrl(i);
}
int str_isdigit(int i)
{
assert(i >= -1 && i < 256);
return isdigit(i);
}
int str_isgraph(int i)
{
assert(i >= -1 && i < 256);
return isgraph(i);
}
int str_islower(int i)
{
assert(i >= -1 && i < 256);
return islower(i);
}
int str_isprint(int i)
{
assert(i >= -1 && i < 256);
return isprint(i);
}
int str_ispunct(int i)
{
assert(i >= -1 && i < 256);
return ispunct(i);
}
int str_isspace(int i)
{
assert(i >= -1 && i < 256);
return isspace(i);
}
int str_isupper(int i)
{
assert(i >= -1 && i < 256);
return isupper(i);
}
int str_isxdigit(int i)
{
assert(i >= -1 && i < 256);
return isxdigit(i);
}
#undef strstr
#undef strchr
#undef strrchr
char *str_strstr(const char *haystack, const char *needle)
{
return strstr(haystack, needle);
}
char *str_strchr(const char *haystack, int c)
{
return strchr(haystack, c);
}
char *str_strrchr(const char *haystack, int c)
{
return strrchr(haystack, c);
}
#endif

13
ccan/ccan/str/str.c Normal file
View file

@ -0,0 +1,13 @@
/* CC0 (Public domain) - see LICENSE file for details */
#include <ccan/str/str.h>
size_t strcount(const char *haystack, const char *needle)
{
size_t i = 0, nlen = strlen(needle);
while ((haystack = strstr(haystack, needle)) != NULL) {
i++;
haystack += nlen;
}
return i;
}

228
ccan/ccan/str/str.h Normal file
View file

@ -0,0 +1,228 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_STR_H
#define CCAN_STR_H
#include "config.h"
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#include <ctype.h>
/**
* streq - Are two strings equal?
* @a: first string
* @b: first string
*
* This macro is arguably more readable than "!strcmp(a, b)".
*
* Example:
* if (streq(somestring, ""))
* printf("String is empty!\n");
*/
#define streq(a,b) (strcmp((a),(b)) == 0)
/**
* strstarts - Does this string start with this prefix?
* @str: string to test
* @prefix: prefix to look for at start of str
*
* Example:
* if (strstarts(somestring, "foo"))
* printf("String %s begins with 'foo'!\n", somestring);
*/
#define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0)
/**
* strends - Does this string end with this postfix?
* @str: string to test
* @postfix: postfix to look for at end of str
*
* Example:
* if (strends(somestring, "foo"))
* printf("String %s end with 'foo'!\n", somestring);
*/
static inline bool strends(const char *str, const char *postfix)
{
if (strlen(str) < strlen(postfix))
return false;
return streq(str + strlen(str) - strlen(postfix), postfix);
}
/**
* stringify - Turn expression into a string literal
* @expr: any C expression
*
* Example:
* #define PRINT_COND_IF_FALSE(cond) \
* ((cond) || printf("%s is false!", stringify(cond)))
*/
#define stringify(expr) stringify_1(expr)
/* Double-indirection required to stringify expansions */
#define stringify_1(expr) #expr
/**
* strcount - Count number of (non-overlapping) occurrences of a substring.
* @haystack: a C string
* @needle: a substring
*
* Example:
* assert(strcount("aaa aaa", "a") == 6);
* assert(strcount("aaa aaa", "ab") == 0);
* assert(strcount("aaa aaa", "aa") == 2);
*/
size_t strcount(const char *haystack, const char *needle);
/**
* STR_MAX_CHARS - Maximum possible size of numeric string for this type.
* @type_or_expr: a pointer or integer type or expression.
*
* This provides enough space for a nul-terminated string which represents the
* largest possible value for the type or expression.
*
* Note: The implementation adds extra space so hex values or negative
* values will fit (eg. sprintf(... "%p"). )
*
* Example:
* char str[STR_MAX_CHARS(int)];
*
* sprintf(str, "%i", 7);
*/
#define STR_MAX_CHARS(type_or_expr) \
((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \
+ STR_MAX_CHARS_TCHECK_(type_or_expr))
#if HAVE_TYPEOF
/* Only a simple type can have 0 assigned, so test that. */
#define STR_MAX_CHARS_TCHECK_(type_or_expr) \
(sizeof(({ typeof(type_or_expr) x = 0; x; }))*0)
#else
#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0
#endif
/**
* cisalnum - isalnum() which takes a char (and doesn't accept EOF)
* @c: a character
*
* Surprisingly, the standard ctype.h isalnum() takes an int, which
* must have the value of EOF (-1) or an unsigned char. This variant
* takes a real char, and doesn't accept EOF.
*/
static inline bool cisalnum(char c)
{
return isalnum((unsigned char)c);
}
static inline bool cisalpha(char c)
{
return isalpha((unsigned char)c);
}
static inline bool cisascii(char c)
{
return isascii((unsigned char)c);
}
#if HAVE_ISBLANK
static inline bool cisblank(char c)
{
return isblank((unsigned char)c);
}
#endif
static inline bool ciscntrl(char c)
{
return iscntrl((unsigned char)c);
}
static inline bool cisdigit(char c)
{
return isdigit((unsigned char)c);
}
static inline bool cisgraph(char c)
{
return isgraph((unsigned char)c);
}
static inline bool cislower(char c)
{
return islower((unsigned char)c);
}
static inline bool cisprint(char c)
{
return isprint((unsigned char)c);
}
static inline bool cispunct(char c)
{
return ispunct((unsigned char)c);
}
static inline bool cisspace(char c)
{
return isspace((unsigned char)c);
}
static inline bool cisupper(char c)
{
return isupper((unsigned char)c);
}
static inline bool cisxdigit(char c)
{
return isxdigit((unsigned char)c);
}
#include <ccan/str/str_debug.h>
/* These checks force things out of line, hence they are under DEBUG. */
#ifdef CCAN_STR_DEBUG
#include <ccan/build_assert/build_assert.h>
/* These are commonly misused: they take -1 or an *unsigned* char value. */
#undef isalnum
#undef isalpha
#undef isascii
#undef isblank
#undef iscntrl
#undef isdigit
#undef isgraph
#undef islower
#undef isprint
#undef ispunct
#undef isspace
#undef isupper
#undef isxdigit
/* You can use a char if char is unsigned. */
#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF
#define str_check_arg_(i) \
((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \
char) \
|| (char)255 > 0))
#else
#define str_check_arg_(i) (i)
#endif
#define isalnum(i) str_isalnum(str_check_arg_(i))
#define isalpha(i) str_isalpha(str_check_arg_(i))
#define isascii(i) str_isascii(str_check_arg_(i))
#if HAVE_ISBLANK
#define isblank(i) str_isblank(str_check_arg_(i))
#endif
#define iscntrl(i) str_iscntrl(str_check_arg_(i))
#define isdigit(i) str_isdigit(str_check_arg_(i))
#define isgraph(i) str_isgraph(str_check_arg_(i))
#define islower(i) str_islower(str_check_arg_(i))
#define isprint(i) str_isprint(str_check_arg_(i))
#define ispunct(i) str_ispunct(str_check_arg_(i))
#define isspace(i) str_isspace(str_check_arg_(i))
#define isupper(i) str_isupper(str_check_arg_(i))
#define isxdigit(i) str_isxdigit(str_check_arg_(i))
#if HAVE_TYPEOF
/* With GNU magic, we can make const-respecting standard string functions. */
#undef strstr
#undef strchr
#undef strrchr
/* + 0 is needed to decay array into pointer. */
#define strstr(haystack, needle) \
((typeof((haystack) + 0))str_strstr((haystack), (needle)))
#define strchr(haystack, c) \
((typeof((haystack) + 0))str_strchr((haystack), (c)))
#define strrchr(haystack, c) \
((typeof((haystack) + 0))str_strrchr((haystack), (c)))
#endif
#endif /* CCAN_STR_DEBUG */
#endif /* CCAN_STR_H */

30
ccan/ccan/str/str_debug.h Normal file
View file

@ -0,0 +1,30 @@
/* CC0 (Public domain) - see LICENSE file for details */
#ifndef CCAN_STR_DEBUG_H
#define CCAN_STR_DEBUG_H
/* #define CCAN_STR_DEBUG 1 */
#ifdef CCAN_STR_DEBUG
/* Because we mug the real ones with macros, we need our own wrappers. */
int str_isalnum(int i);
int str_isalpha(int i);
int str_isascii(int i);
#if HAVE_ISBLANK
int str_isblank(int i);
#endif
int str_iscntrl(int i);
int str_isdigit(int i);
int str_isgraph(int i);
int str_islower(int i);
int str_isprint(int i);
int str_ispunct(int i);
int str_isspace(int i);
int str_isupper(int i);
int str_isxdigit(int i);
char *str_strstr(const char *haystack, const char *needle);
char *str_strchr(const char *s, int c);
char *str_strrchr(const char *s, int c);
#endif /* CCAN_STR_DEBUG */
#endif /* CCAN_STR_DEBUG_H */

17
ccan/licenses/BSD-MIT Normal file
View file

@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

28
ccan/licenses/CC0 Normal file
View file

@ -0,0 +1,28 @@
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
moral rights retained by the original author(s) and/or performer(s);
publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
rights protecting the extraction, dissemination, use and reuse of data in a Work;
database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.

26
ccan/meson.build Normal file
View file

@ -0,0 +1,26 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of libnvme.
# Copyright (c) 2021 Dell Inc.
#
# Authors: Martin Belanger <Martin.Belanger@dell.com>
#
sources = [
'ccan/list/list.c',
'ccan/str/debug.c',
'ccan/str/str.c',
]
if get_option('buildtype') == 'debug'
add_project_arguments('-DCCAN_LIST_DEBUG=1', language : ['c', 'cpp'])
add_project_arguments('-DCCAN_STR_DEBUG=1', language : ['c', 'cpp'])
endif
libccan = static_library(
'ccan',
sources,
install: false,
include_directories: [incdir, internal_incdir],
dependencies: config_dep,
)

73
doc/conf.py Normal file
View file

@ -0,0 +1,73 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'libnvme'
copyright = '2020, Keith Busch'
author = 'Keith Busch <kbusch@kernel.org>'
master_doc = 'libnvme'
# The full version, including alpha/beta/rc tags
release = '0.1'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['html', 'man', 'index.rst', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
#html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['sphinx-static']
html_context = {
'css_files': [
'_static/theme_overrides.css',
],
}
html_use_smartypants = False
pygments_style = 'sphinx'
htmlhelp_basename = 'libnvme'
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
except ImportError:
sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n')

164
doc/config-schema.json Normal file
View file

@ -0,0 +1,164 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/linux-nvme/libnvme/doc/config-schema.json",
"title": "config.json",
"description": "libnvme JSON configuration",
"type": "object",
"properties": {
"hosts": {
"description": "Array of NVMe Host properties",
"type": "array",
"items": { "$ref": "#/$defs/host" }
}
},
"$defs": {
"host": {
"description": "NVMe Host properties",
"type": "object",
"properties": {
"hostnqn": {
"description": "NVMe host NQN",
"type": "string",
"maxLength": 223
},
"hostid": {
"description": "NVMe host ID",
"type": "string"
},
"hostsymname": {
"description": "NVMe host symbolic name",
"type": "string"
},
"required": [ "hostnqn" ],
"subsystems": {
"description": "Array of NVMe subsystem properties",
"type": "array",
"items": { "$ref": "#/$defs/subsystem" }
}
}
},
"subsystem": {
"description": "NVMe subsystem properties",
"type": "object",
"properties": {
"nqn": {
"description": "Subsystem NQN",
"type": "string",
"maxLength": 223
},
"ports": {
"description": "Array of NVMe subsystem ports",
"type": "array",
"items": { "$ref": "#/$defs/port" }
},
"required": [ "nqn" ]
}
},
"port": {
"description": "NVMe subsystem port",
"type": "object",
"properties": {
"transport": {
"description": "Transport type",
"type": "string"
},
"traddr": {
"description": "Transport address",
"type": "string"
},
"host_traddr": {
"description": "Host transport address",
"type": "string"
},
"host_iface": {
"description": "Host interface name",
"type": "string"
},
"trsvcid": {
"description": "Transport service identifier",
"type": "string"
},
"dhchap_key": {
"description": "Host DH-HMAC-CHAP key",
"type": "string"
},
"dhchap_ctrl_key": {
"description": "Controller DH-HMAC-CHAP key",
"type": "string"
},
"nr_io_queues": {
"description": "Number of I/O queues",
"type": "integer"
},
"nr_write_queues": {
"description": "Number of write queues",
"type": "integer"
},
"nr_poll_queues": {
"description": "Number of poll queues",
"type": "integer"
},
"queue_size": {
"description": "Queue size",
"type": "integer"
},
"keep_alive_tmo": {
"description": "Keep-Alive timeout (in seconds)",
"type": "integer"
},
"reconnect_delay": {
"description": "Reconnect delay (in seconds)",
"type": "integer"
},
"ctrl_loss_tmo": {
"description": "Controller loss timeout (in seconds)",
"type": "integer"
},
"fast_io_fail_tmo": {
"description": "Fast I/O Fail timeout (in seconds)",
"type": "integer",
"default": 600
},
"tos": {
"description": "Type of service",
"type": "integer",
"default": -1
},
"duplicate_connect": {
"description": "Allow duplicate connections",
"type": "boolean",
"default": false
},
"disable_sqflow": {
"description": "Explicitly disable SQ flow control",
"type": "boolean",
"default": false
},
"hdr_digest": {
"description": "Enable header digest",
"type": "boolean",
"default": false
},
"data_digest": {
"description": "Enable data digest",
"type": "boolean",
"default": false
},
"tls": {
"description": "Enable TLS encryption",
"type": "boolean",
"default": false
},
"persistent": {
"description": "Create persistent discovery connection",
"type": "boolean"
},
"discovery": {
"description": "Connect to a discovery controller",
"type": "boolean"
}
},
"required": [ "transport" ]
}
}
}

21
doc/index.rst Normal file
View file

@ -0,0 +1,21 @@
.. libnvme documentation master file, created by
sphinx-quickstart on Thu Feb 6 17:59:42 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to libnvme's documentation!
===================================
.. toctree::
:maxdepth: 2
:caption: Contents:
libnvme
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

2523
doc/kernel-doc Executable file

File diff suppressed because it is too large Load diff

15
doc/list-man-pages.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
file=$1
for func in $(sed -n 's/ \* \([a-z_]*\)() -.*/\1/p' $file); do
echo ${func}
done
for struct in $(sed -n 's/ \* struct \([a-z_]*\) -.*/\1/p' $file); do
echo ${struct}
done
for enum in $(sed -n 's/ \* enum \([a-z_]*\) -.*/\1/p' $file); do
echo ${enum}
done

216
doc/man/nvme_admin_opcode.2 Normal file
View file

@ -0,0 +1,216 @@
.TH "libnvme" 9 "enum nvme_admin_opcode" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_admin_opcode \- Known NVMe admin opcodes
.SH SYNOPSIS
enum nvme_admin_opcode {
.br
.BI " nvme_admin_delete_sq"
,
.br
.br
.BI " nvme_admin_create_sq"
,
.br
.br
.BI " nvme_admin_get_log_page"
,
.br
.br
.BI " nvme_admin_delete_cq"
,
.br
.br
.BI " nvme_admin_create_cq"
,
.br
.br
.BI " nvme_admin_identify"
,
.br
.br
.BI " nvme_admin_abort_cmd"
,
.br
.br
.BI " nvme_admin_set_features"
,
.br
.br
.BI " nvme_admin_get_features"
,
.br
.br
.BI " nvme_admin_async_event"
,
.br
.br
.BI " nvme_admin_ns_mgmt"
,
.br
.br
.BI " nvme_admin_fw_commit"
,
.br
.br
.BI " nvme_admin_fw_activate"
,
.br
.br
.BI " nvme_admin_fw_download"
,
.br
.br
.BI " nvme_admin_dev_self_test"
,
.br
.br
.BI " nvme_admin_ns_attach"
,
.br
.br
.BI " nvme_admin_keep_alive"
,
.br
.br
.BI " nvme_admin_directive_send"
,
.br
.br
.BI " nvme_admin_directive_recv"
,
.br
.br
.BI " nvme_admin_virtual_mgmt"
,
.br
.br
.BI " nvme_admin_nvme_mi_send"
,
.br
.br
.BI " nvme_admin_nvme_mi_recv"
,
.br
.br
.BI " nvme_admin_capacity_mgmt"
,
.br
.br
.BI " nvme_admin_discovery_info_mgmt"
,
.br
.br
.BI " nvme_admin_fabric_zoning_recv"
,
.br
.br
.BI " nvme_admin_lockdown"
,
.br
.br
.BI " nvme_admin_fabric_zoning_lookup"
,
.br
.br
.BI " nvme_admin_fabric_zoning_send"
,
.br
.br
.BI " nvme_admin_dbbuf"
,
.br
.br
.BI " nvme_admin_fabrics"
,
.br
.br
.BI " nvme_admin_format_nvm"
,
.br
.br
.BI " nvme_admin_security_send"
,
.br
.br
.BI " nvme_admin_security_recv"
,
.br
.br
.BI " nvme_admin_sanitize_nvm"
,
.br
.br
.BI " nvme_admin_get_lba_status"
};
.SH Constants
.IP "nvme_admin_delete_sq" 12
Delete I/O Submission Queue
.IP "nvme_admin_create_sq" 12
Create I/O Submission Queue
.IP "nvme_admin_get_log_page" 12
Get Log Page
.IP "nvme_admin_delete_cq" 12
Delete I/O Completion Queue
.IP "nvme_admin_create_cq" 12
Create I/O Completion Queue
.IP "nvme_admin_identify" 12
Identify
.IP "nvme_admin_abort_cmd" 12
Abort
.IP "nvme_admin_set_features" 12
Set Features
.IP "nvme_admin_get_features" 12
Get Features
.IP "nvme_admin_async_event" 12
Asynchronous Event Request
.IP "nvme_admin_ns_mgmt" 12
Namespace Management
.IP "nvme_admin_fw_commit" 12
Firmware Commit
.IP "nvme_admin_fw_activate" 12
Firmware Commit
.IP "nvme_admin_fw_download" 12
Firmware Image Download
.IP "nvme_admin_dev_self_test" 12
Device Self-test
.IP "nvme_admin_ns_attach" 12
Namespace Attachment
.IP "nvme_admin_keep_alive" 12
Keep Alive
.IP "nvme_admin_directive_send" 12
Directive Send
.IP "nvme_admin_directive_recv" 12
Directive Receive
.IP "nvme_admin_virtual_mgmt" 12
Virtualization Management
.IP "nvme_admin_nvme_mi_send" 12
NVMe-MI Send
.IP "nvme_admin_nvme_mi_recv" 12
NVMe-MI Receive
.IP "nvme_admin_capacity_mgmt" 12
Capacity Management
.IP "nvme_admin_discovery_info_mgmt" 12
Discovery Information Management (DIM)
.IP "nvme_admin_fabric_zoning_recv" 12
Fabric Zoning Receive
.IP "nvme_admin_lockdown" 12
Lockdown
.IP "nvme_admin_fabric_zoning_lookup" 12
Fabric Zoning Lookup
.IP "nvme_admin_fabric_zoning_send" 12
Fabric Zoning Send
.IP "nvme_admin_dbbuf" 12
Doorbell Buffer Config
.IP "nvme_admin_fabrics" 12
Fabrics Commands
.IP "nvme_admin_format_nvm" 12
Format NVM
.IP "nvme_admin_security_send" 12
Security Send
.IP "nvme_admin_security_recv" 12
Security Receive
.IP "nvme_admin_sanitize_nvm" 12
Sanitize
.IP "nvme_admin_get_lba_status" 12
Get LBA Status

View file

@ -0,0 +1,71 @@
.TH "nvme_admin_passthru" 9 "nvme_admin_passthru" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_admin_passthru \- Submit an nvme passthrough command
.SH SYNOPSIS
.B "int" nvme_admin_passthru
.BI "(int fd " ","
.BI "__u8 opcode " ","
.BI "__u8 flags " ","
.BI "__u16 rsvd " ","
.BI "__u32 nsid " ","
.BI "__u32 cdw2 " ","
.BI "__u32 cdw3 " ","
.BI "__u32 cdw10 " ","
.BI "__u32 cdw11 " ","
.BI "__u32 cdw12 " ","
.BI "__u32 cdw13 " ","
.BI "__u32 cdw14 " ","
.BI "__u32 cdw15 " ","
.BI "__u32 data_len " ","
.BI "void *data " ","
.BI "__u32 metadata_len " ","
.BI "void *metadata " ","
.BI "__u32 timeout_ms " ","
.BI "__u32 *result " ");"
.SH ARGUMENTS
.IP "fd" 12
File descriptor of nvme device
.IP "opcode" 12
The nvme io command to send
.IP "flags" 12
NVMe command flags (not used)
.IP "rsvd" 12
Reserevd for future use
.IP "nsid" 12
Namespace identifier
.IP "cdw2" 12
Command dword 2
.IP "cdw3" 12
Command dword 3
.IP "cdw10" 12
Command dword 10
.IP "cdw11" 12
Command dword 11
.IP "cdw12" 12
Command dword 12
.IP "cdw13" 12
Command dword 13
.IP "cdw14" 12
Command dword 14
.IP "cdw15" 12
Command dword 15
.IP "data_len" 12
Length of the data transfered in this command in bytes
.IP "data" 12
Pointer to user address of the data buffer
.IP "metadata_len" 12
Length of metadata transfered in this command
.IP "metadata" 12
Pointer to user address of the metadata buffer
.IP "timeout_ms" 12
How long the kernel waits for the command to complete
.IP "result" 12
Optional field to return the result from the CQE dword 0
.SH "DESCRIPTION"
Parameterized form of \fBnvme_submit_admin_passthru\fP. This sets up and
submits a \fIstruct nvme_passthru_cmd\fP.
Known values for \fIopcode\fP are defined in \fIenum nvme_admin_opcode\fP.
.SH "RETURN"
The nvme command status if a response was received (see
\fIenum nvme_status_field\fP) or -1 with errno set otherwise.

View file

@ -0,0 +1,25 @@
.TH "libnvme" 9 "enum nvme_ae_info_css_nvm" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_ae_info_css_nvm \-
.SH SYNOPSIS
enum nvme_ae_info_css_nvm {
.br
.BI " NVME_AER_CSS_NVM_RESERVATION"
,
.br
.br
.BI " NVME_AER_CSS_NVM_SANITIZE_COMPLETED"
,
.br
.br
.BI " NVME_AER_CSS_NVM_UNEXPECTED_SANITIZE_DEALLOC"
};
.SH Constants
.IP "NVME_AER_CSS_NVM_RESERVATION" 12
Reservation Log Page Available
.IP "NVME_AER_CSS_NVM_SANITIZE_COMPLETED" 12
Sanitize Operation Completed
.IP "NVME_AER_CSS_NVM_UNEXPECTED_SANITIZE_DEALLOC" 12
Sanitize Operation Completed
With Unexpected Deallocation

View file

@ -0,0 +1,42 @@
.TH "libnvme" 9 "enum nvme_ae_info_error" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_ae_info_error \-
.SH SYNOPSIS
enum nvme_ae_info_error {
.br
.BI " NVME_AER_ERROR_INVALID_DB_REG"
,
.br
.br
.BI " NVME_AER_ERROR_INVALID_DB_VAL"
,
.br
.br
.BI " NVME_AER_ERROR_DIAG_FAILURE"
,
.br
.br
.BI " NVME_AER_ERROR_PERSISTENT_INTERNAL_ERROR"
,
.br
.br
.BI " NVME_AER_ERROR_TRANSIENT_INTERNAL_ERROR"
,
.br
.br
.BI " NVME_AER_ERROR_FW_IMAGE_LOAD_ERROR"
};
.SH Constants
.IP "NVME_AER_ERROR_INVALID_DB_REG" 12
Write to Invalid Doorbell Register
.IP "NVME_AER_ERROR_INVALID_DB_VAL" 12
Invalid Doorbell Write Value
.IP "NVME_AER_ERROR_DIAG_FAILURE" 12
Diagnostic Failure
.IP "NVME_AER_ERROR_PERSISTENT_INTERNAL_ERROR" 12
Persistent Internal Error
.IP "NVME_AER_ERROR_TRANSIENT_INTERNAL_ERROR" 12
Transient Internal Error
.IP "NVME_AER_ERROR_FW_IMAGE_LOAD_ERROR" 12
Firmware Image Load Error

View file

@ -0,0 +1,54 @@
.TH "libnvme" 9 "enum nvme_ae_info_notice" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_ae_info_notice \-
.SH SYNOPSIS
enum nvme_ae_info_notice {
.br
.BI " NVME_AER_NOTICE_NS_CHANGED"
,
.br
.br
.BI " NVME_AER_NOTICE_FW_ACT_STARTING"
,
.br
.br
.BI " NVME_AER_NOTICE_TELEMETRY"
,
.br
.br
.BI " NVME_AER_NOTICE_ANA"
,
.br
.br
.BI " NVME_AER_NOTICE_PL_EVENT"
,
.br
.br
.BI " NVME_AER_NOTICE_LBA_STATUS_ALERT"
,
.br
.br
.BI " NVME_AER_NOTICE_EG_EVENT"
,
.br
.br
.BI " NVME_AER_NOTICE_DISC_CHANGED"
};
.SH Constants
.IP "NVME_AER_NOTICE_NS_CHANGED" 12
Namespace Attribute Changed
.IP "NVME_AER_NOTICE_FW_ACT_STARTING" 12
Firmware Activation Starting
.IP "NVME_AER_NOTICE_TELEMETRY" 12
Telemetry Log Changed
.IP "NVME_AER_NOTICE_ANA" 12
Asymmetric Namespace Access Change
.IP "NVME_AER_NOTICE_PL_EVENT" 12
Predictable Latency Event Aggregate Log Change
.IP "NVME_AER_NOTICE_LBA_STATUS_ALERT" 12
LBA Status Information Alert
.IP "NVME_AER_NOTICE_EG_EVENT" 12
Endurance Group Event Aggregate Log Page Change
.IP "NVME_AER_NOTICE_DISC_CHANGED" 12
Discovery Log Page Change

View file

@ -0,0 +1,24 @@
.TH "libnvme" 9 "enum nvme_ae_info_smart" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_ae_info_smart \-
.SH SYNOPSIS
enum nvme_ae_info_smart {
.br
.BI " NVME_AER_SMART_SUBSYSTEM_RELIABILITY"
,
.br
.br
.BI " NVME_AER_SMART_TEMPERATURE_THRESHOLD"
,
.br
.br
.BI " NVME_AER_SMART_SPARE_THRESHOLD"
};
.SH Constants
.IP "NVME_AER_SMART_SUBSYSTEM_RELIABILITY" 12
NVM subsystem Reliability
.IP "NVME_AER_SMART_TEMPERATURE_THRESHOLD" 12
Temperature Threshold
.IP "NVME_AER_SMART_SPARE_THRESHOLD" 12
Spare Below Threshold

36
doc/man/nvme_ae_type.2 Normal file
View file

@ -0,0 +1,36 @@
.TH "libnvme" 9 "enum nvme_ae_type" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_ae_type \-
.SH SYNOPSIS
enum nvme_ae_type {
.br
.BI " NVME_AER_ERROR"
,
.br
.br
.BI " NVME_AER_SMART"
,
.br
.br
.BI " NVME_AER_NOTICE"
,
.br
.br
.BI " NVME_AER_CSS"
,
.br
.br
.BI " NVME_AER_VS"
};
.SH Constants
.IP "NVME_AER_ERROR" 12
Error event
.IP "NVME_AER_SMART" 12
SMART / Health Status event
.IP "NVME_AER_NOTICE" 12
Notice event
.IP "NVME_AER_CSS" 12
NVM Command Set Specific events
.IP "NVME_AER_VS" 12
Vendor Specific event

View file

@ -0,0 +1,19 @@
.TH "libnvme" 9 "struct nvme_aggregate_endurance_group_event" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_aggregate_endurance_group_event \-
.SH SYNOPSIS
struct nvme_aggregate_endurance_group_event {
.br
.BI " __le64 num_entries;"
.br
.BI " __le16 entries[];"
.br
.BI "
};
.br
.SH Members
.IP "num_entries" 12
Number or entries
.IP "entries" 12
List of entries

View file

@ -0,0 +1,19 @@
.TH "libnvme" 9 "struct nvme_aggregate_predictable_lat_event" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_aggregate_predictable_lat_event \-
.SH SYNOPSIS
struct nvme_aggregate_predictable_lat_event {
.br
.BI " __le64 num_entries;"
.br
.BI " __le16 entries[];"
.br
.BI "
};
.br
.SH Members
.IP "num_entries" 12
Number of entries
.IP "entries" 12
Entry list

View file

@ -0,0 +1,35 @@
.TH "libnvme" 9 "struct nvme_ana_group_desc" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_ana_group_desc \-
.SH SYNOPSIS
struct nvme_ana_group_desc {
.br
.BI " __le32 grpid;"
.br
.BI " __le32 nnsids;"
.br
.BI " __le64 chgcnt;"
.br
.BI " __u8 state;"
.br
.BI " __u8 rsvd17[15];"
.br
.BI " __le32 nsids[];"
.br
.BI "
};
.br
.SH Members
.IP "grpid" 12
ANA group id
.IP "nnsids" 12
Number of namespaces in \fInsids\fP
.IP "chgcnt" 12
Change counter
.IP "state" 12
ANA state
.IP "rsvd17" 12
Reserved
.IP "nsids" 12
List of namespaces

27
doc/man/nvme_ana_log.2 Normal file
View file

@ -0,0 +1,27 @@
.TH "libnvme" 9 "struct nvme_ana_log" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_ana_log \-
.SH SYNOPSIS
struct nvme_ana_log {
.br
.BI " __le64 chgcnt;"
.br
.BI " __le16 ngrps;"
.br
.BI " __u8 rsvd10[6];"
.br
.BI " struct nvme_ana_group_desc descs[];"
.br
.BI "
};
.br
.SH Members
.IP "chgcnt" 12
Change Count
.IP "ngrps" 12
Number of ANA Group Descriptors
.IP "rsvd10" 12
Reserved
.IP "descs" 12
ANA Group Descriptor

31
doc/man/nvme_ana_state.2 Normal file
View file

@ -0,0 +1,31 @@
.TH "libnvme" 9 "enum nvme_ana_state" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_ana_state \-
.SH SYNOPSIS
enum nvme_ana_state {
.br
.BI " NVME_ANA_STATE_OPTIMIZED"
,
.br
.br
.BI " NVME_ANA_STATE_NONOPTIMIZED"
,
.br
.br
.BI " NVME_ANA_STATE_INACCESSIBLE"
,
.br
.br
.BI " NVME_ANA_STATE_PERSISTENT_LOSS"
,
.br
.br
.BI " NVME_ANA_STATE_CHANGE"
};
.SH Constants
.IP "NVME_ANA_STATE_OPTIMIZED" 12
.IP "NVME_ANA_STATE_NONOPTIMIZED" 12
.IP "NVME_ANA_STATE_INACCESSIBLE" 12
.IP "NVME_ANA_STATE_PERSISTENT_LOSS" 12
.IP "NVME_ANA_STATE_CHANGE" 12

26
doc/man/nvme_apst_entry.2 Normal file
View file

@ -0,0 +1,26 @@
.TH "libnvme" 9 "enum nvme_apst_entry" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_apst_entry \-
.SH SYNOPSIS
enum nvme_apst_entry {
.br
.BI " NVME_APST_ENTRY_ITPS_SHIFT"
,
.br
.br
.BI " NVME_APST_ENTRY_ITPT_SHIFT"
,
.br
.br
.BI " NVME_APST_ENTRY_ITPS_MASK"
,
.br
.br
.BI " NVME_APST_ENTRY_ITPT_MASK"
};
.SH Constants
.IP "NVME_APST_ENTRY_ITPS_SHIFT" 12
.IP "NVME_APST_ENTRY_ITPT_SHIFT" 12
.IP "NVME_APST_ENTRY_ITPS_MASK" 12
.IP "NVME_APST_ENTRY_ITPT_MASK" 12

View file

@ -0,0 +1,32 @@
.TH "libnvme" 9 "struct nvme_boot_partition" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_boot_partition \-
.SH SYNOPSIS
struct nvme_boot_partition {
.br
.BI " __u8 lid;"
.br
.BI " __u8 rsvd1[3];"
.br
.BI " __le32 bpinfo;"
.br
.BI " __u8 rsvd8[8];"
.br
.BI " __u8 boot_partition_data[];"
.br
.BI "
};
.br
.SH Members
.IP "lid" 12
Boot Partition Identifier
.IP "rsvd1" 12
Reserved
.IP "bpinfo" 12
Boot Partition Information
.IP "rsvd8" 12
Reserved
.IP "boot_partition_data" 12
Contains the contents of the
specified Boot Partition

View file

View file

@ -0,0 +1,12 @@
.TH "nvme_capacity_mgmt" 9 "nvme_capacity_mgmt" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_capacity_mgmt \-
.SH SYNOPSIS
.B "int" nvme_capacity_mgmt
.BI "(struct nvme_capacity_mgmt_args *args " ");"
.SH ARGUMENTS
.IP "args" 12
\fIstruct nvme_capacity_mgmt_args\fP argument structure
.SH "RETURN"
The nvme command status if a response was received (see
\fIenum nvme_status_field\fP) or -1 with errno set otherwise.

View file

@ -0,0 +1,45 @@
.TH "libnvme" 9 "struct nvme_capacity_mgmt_args" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_capacity_mgmt_args \- Arguments for the NVMe Capacity Management command
.SH SYNOPSIS
struct nvme_capacity_mgmt_args {
.br
.BI " __u32 *result;"
.br
.BI " int args_size;"
.br
.BI " int fd;"
.br
.BI " __u32 timeout;"
.br
.BI " __u32 cdw11;"
.br
.BI " __u32 cdw12;"
.br
.BI " __u16 element_id;"
.br
.BI " __u8 op;"
.br
.BI "
};
.br
.SH Members
.IP "result" 12
If successful, the CQE dword0 value
.IP "args_size" 12
Size of \fIstruct nvme_capacity_mgmt_args\fP
.IP "fd" 12
File descriptor of nvme device
.IP "timeout" 12
Timeout in ms
.IP "cdw11" 12
Least significant 32 bits of the capacity in bytes of the
Endurance Group or NVM Set to be created
.IP "cdw12" 12
Most significant 32 bits of the capacity in bytes of the
Endurance Group or NVM Set to be created
.IP "element_id" 12
Value specific to the value of the Operation field
.IP "op" 12
Operation to be performed by the controller

View file

@ -0,0 +1,63 @@
.TH "libnvme" 9 "struct nvme_change_ns_event" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_change_ns_event \-
.SH SYNOPSIS
struct nvme_change_ns_event {
.br
.BI " __le32 nsmgt_cdw10;"
.br
.BI " __u8 rsvd4[4];"
.br
.BI " __le64 nsze;"
.br
.BI " __u8 rsvd16[8];"
.br
.BI " __le64 nscap;"
.br
.BI " __u8 flbas;"
.br
.BI " __u8 dps;"
.br
.BI " __u8 nmic;"
.br
.BI " __u8 rsvd35;"
.br
.BI " __le32 ana_grp_id;"
.br
.BI " __le16 nvmset_id;"
.br
.BI " __le16 rsvd42;"
.br
.BI " __le32 nsid;"
.br
.BI "
};
.br
.SH Members
.IP "nsmgt_cdw10" 12
Namespace Management CDW10
.IP "rsvd4" 12
Reserved
.IP "nsze" 12
Namespace Size
.IP "rsvd16" 12
Reserved
.IP "nscap" 12
Namespace Capacity
.IP "flbas" 12
Formatted LBA Size
.IP "dps" 12
End-to-end Data Protection Type Settings
.IP "nmic" 12
Namespace Multi-path I/O and Namespace Sharing Capabilities
.IP "rsvd35" 12
Reserved
.IP "ana_grp_id" 12
ANA Group Identifier
.IP "nvmset_id" 12
NVM Set Identifier
.IP "rsvd42" 12
Reserved
.IP "nsid" 12
Namespace ID

View file

@ -0,0 +1,24 @@
.TH "libnvme" 9 "struct nvme_channel_config_desc" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_channel_config_desc \-
.SH SYNOPSIS
struct nvme_channel_config_desc {
.br
.BI " __le16 chanid;"
.br
.BI " __le16 chmus;"
.br
.BI " struct nvme_media_unit_config_desc mu_config_desc[];"
.br
.BI "
};
.br
.SH Members
.IP "chanid" 12
Channel Identifier
.IP "chmus" 12
Number Channel Media Units
.SH "Description"
Channel Configuration Descriptor
Structure Definitions

11
doc/man/nvme_cmb_size.2 Normal file
View file

@ -0,0 +1,11 @@
.TH "nvme_cmb_size" 9 "nvme_cmb_size" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_cmb_size \- Calculate size of the controller memory buffer
.SH SYNOPSIS
.B "__u64" nvme_cmb_size
.BI "(__u32 cmbsz " ");"
.SH ARGUMENTS
.IP "cmbsz" 12
Value from controller register NVME_REG_CMBSZ
.SH "DESCRIPTION"
Returns size of controller memory buffer in bytes

View file

@ -0,0 +1,48 @@
.TH "libnvme" 9 "enum nvme_cmd_effects" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_effects \-
.SH SYNOPSIS
enum nvme_cmd_effects {
.br
.BI " NVME_CMD_EFFECTS_CSUPP"
,
.br
.br
.BI " NVME_CMD_EFFECTS_LBCC"
,
.br
.br
.BI " NVME_CMD_EFFECTS_NCC"
,
.br
.br
.BI " NVME_CMD_EFFECTS_NIC"
,
.br
.br
.BI " NVME_CMD_EFFECTS_CCC"
,
.br
.br
.BI " NVME_CMD_EFFECTS_CSE_MASK"
,
.br
.br
.BI " NVME_CMD_EFFECTS_UUID_SEL"
};
.SH Constants
.IP "NVME_CMD_EFFECTS_CSUPP" 12
Command Supported
.IP "NVME_CMD_EFFECTS_LBCC" 12
Logical Block Content Change
.IP "NVME_CMD_EFFECTS_NCC" 12
Namespace Capability Change
.IP "NVME_CMD_EFFECTS_NIC" 12
Namespace Inventory Change
.IP "NVME_CMD_EFFECTS_CCC" 12
Controller Capability Change
.IP "NVME_CMD_EFFECTS_CSE_MASK" 12
Command Submission and Execution
.IP "NVME_CMD_EFFECTS_UUID_SEL" 12
UUID Selection Supported

View file

@ -0,0 +1,23 @@
.TH "libnvme" 9 "struct nvme_cmd_effects_log" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_cmd_effects_log \-
.SH SYNOPSIS
struct nvme_cmd_effects_log {
.br
.BI " __le32 acs[256];"
.br
.BI " __le32 iocs[256];"
.br
.BI " __u8 rsvd[2048];"
.br
.BI "
};
.br
.SH Members
.IP "acs" 12
Admin Command Supported
.IP "iocs" 12
I/O Command Supported
.IP "rsvd" 12
Reserved

View file

@ -0,0 +1,20 @@
.TH "libnvme" 9 "enum nvme_cmd_format_mset" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_format_mset \- Format NVM - Metadata Settings
.SH SYNOPSIS
enum nvme_cmd_format_mset {
.br
.BI " NVME_FORMAT_MSET_SEPARATE"
,
.br
.br
.BI " NVME_FORMAT_MSET_EXTENDED"
};
.SH Constants
.IP "NVME_FORMAT_MSET_SEPARATE" 12
indicates that the metadata is transferred
as part of a separate buffer.
.IP "NVME_FORMAT_MSET_EXTENDED" 12
indicates that the metadata is transferred
as part of an extended data LBA.

View file

@ -0,0 +1,30 @@
.TH "libnvme" 9 "enum nvme_cmd_format_pi" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_format_pi \- Format NVM - Protection Information
.SH SYNOPSIS
enum nvme_cmd_format_pi {
.br
.BI " NVME_FORMAT_PI_DISABLE"
,
.br
.br
.BI " NVME_FORMAT_PI_TYPE1"
,
.br
.br
.BI " NVME_FORMAT_PI_TYPE2"
,
.br
.br
.BI " NVME_FORMAT_PI_TYPE3"
};
.SH Constants
.IP "NVME_FORMAT_PI_DISABLE" 12
Protection information is not enabled.
.IP "NVME_FORMAT_PI_TYPE1" 12
Protection information is enabled, Type 1.
.IP "NVME_FORMAT_PI_TYPE2" 12
Protection information is enabled, Type 2.
.IP "NVME_FORMAT_PI_TYPE3" 12
Protection information is enabled, Type 3.

View file

@ -0,0 +1,20 @@
.TH "libnvme" 9 "enum nvme_cmd_format_pil" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_format_pil \- Format NVM - Protection Information Location
.SH SYNOPSIS
enum nvme_cmd_format_pil {
.br
.BI " NVME_FORMAT_PIL_LAST"
,
.br
.br
.BI " NVME_FORMAT_PIL_FIRST"
};
.SH Constants
.IP "NVME_FORMAT_PIL_LAST" 12
Protection information is transferred as the last
bytes of metadata.
.IP "NVME_FORMAT_PIL_FIRST" 12
Protection information is transferred as the first
bytes of metadata.

View file

@ -0,0 +1,33 @@
.TH "libnvme" 9 "enum nvme_cmd_format_ses" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_format_ses \- Format NVM - Secure Erase Settings
.SH SYNOPSIS
enum nvme_cmd_format_ses {
.br
.BI " NVME_FORMAT_SES_NONE"
,
.br
.br
.BI " NVME_FORMAT_SES_USER_DATA_ERASE"
,
.br
.br
.BI " NVME_FORMAT_SES_CRYPTO_ERASE"
};
.SH Constants
.IP "NVME_FORMAT_SES_NONE" 12
No secure erase operation requested.
.IP "NVME_FORMAT_SES_USER_DATA_ERASE" 12
User Data Erase: All user data shall be erased,
contents of the user data after the erase is
indeterminate (e.g. the user data may be zero
filled, one filled, etc.). If a User Data Erase
is requested and all affected user data is
encrypted, then the controller is allowed
to use a cryptographic erase to perform
the requested User Data Erase.
.IP "NVME_FORMAT_SES_CRYPTO_ERASE" 12
Cryptographic Erase: All user data shall
be erased cryptographically. This is
accomplished by deleting the encryption key.

View file

@ -0,0 +1,156 @@
.TH "libnvme" 9 "enum nvme_cmd_get_log_lid" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_get_log_lid \-
.SH SYNOPSIS
enum nvme_cmd_get_log_lid {
.br
.BI " NVME_LOG_LID_SUPPORTED_LOG_PAGES"
,
.br
.br
.BI " NVME_LOG_LID_ERROR"
,
.br
.br
.BI " NVME_LOG_LID_SMART"
,
.br
.br
.BI " NVME_LOG_LID_FW_SLOT"
,
.br
.br
.BI " NVME_LOG_LID_CHANGED_NS"
,
.br
.br
.BI " NVME_LOG_LID_CMD_EFFECTS"
,
.br
.br
.BI " NVME_LOG_LID_DEVICE_SELF_TEST"
,
.br
.br
.BI " NVME_LOG_LID_TELEMETRY_HOST"
,
.br
.br
.BI " NVME_LOG_LID_TELEMETRY_CTRL"
,
.br
.br
.BI " NVME_LOG_LID_ENDURANCE_GROUP"
,
.br
.br
.BI " NVME_LOG_LID_PREDICTABLE_LAT_NVMSET"
,
.br
.br
.BI " NVME_LOG_LID_PREDICTABLE_LAT_AGG"
,
.br
.br
.BI " NVME_LOG_LID_ANA"
,
.br
.br
.BI " NVME_LOG_LID_PERSISTENT_EVENT"
,
.br
.br
.BI " NVME_LOG_LID_LBA_STATUS"
,
.br
.br
.BI " NVME_LOG_LID_ENDURANCE_GRP_EVT"
,
.br
.br
.BI " NVME_LOG_LID_MEDIA_UNIT_STATUS"
,
.br
.br
.BI " NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST"
,
.br
.br
.BI " NVME_LOG_LID_FID_SUPPORTED_EFFECTS"
,
.br
.br
.BI " NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS"
,
.br
.br
.BI " NVME_LOG_LID_BOOT_PARTITION"
,
.br
.br
.BI " NVME_LOG_LID_DISCOVER"
,
.br
.br
.BI " NVME_LOG_LID_RESERVATION"
,
.br
.br
.BI " NVME_LOG_LID_SANITIZE"
,
.br
.br
.BI " NVME_LOG_LID_ZNS_CHANGED_ZONES"
};
.SH Constants
.IP "NVME_LOG_LID_SUPPORTED_LOG_PAGES" 12
Supported Log Pages
.IP "NVME_LOG_LID_ERROR" 12
Error Information
.IP "NVME_LOG_LID_SMART" 12
SMART / Health Information
.IP "NVME_LOG_LID_FW_SLOT" 12
Firmware Slot Information
.IP "NVME_LOG_LID_CHANGED_NS" 12
Changed Namespace List
.IP "NVME_LOG_LID_CMD_EFFECTS" 12
Commands Supported and Effects
.IP "NVME_LOG_LID_DEVICE_SELF_TEST" 12
Device Self-test
.IP "NVME_LOG_LID_TELEMETRY_HOST" 12
Telemetry Host-Initiated
.IP "NVME_LOG_LID_TELEMETRY_CTRL" 12
Telemetry Controller-Initiated
.IP "NVME_LOG_LID_ENDURANCE_GROUP" 12
Endurance Group Information
.IP "NVME_LOG_LID_PREDICTABLE_LAT_NVMSET" 12
Predictable Latency Per NVM Set
.IP "NVME_LOG_LID_PREDICTABLE_LAT_AGG" 12
Predictable Latency Event Aggregate
.IP "NVME_LOG_LID_ANA" 12
Asymmetric Namespace Access
.IP "NVME_LOG_LID_PERSISTENT_EVENT" 12
Persistent Event Log
.IP "NVME_LOG_LID_LBA_STATUS" 12
LBA Status Information
.IP "NVME_LOG_LID_ENDURANCE_GRP_EVT" 12
Endurance Group Event Aggregate
.IP "NVME_LOG_LID_MEDIA_UNIT_STATUS" 12
Media Unit Status
.IP "NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST" 12
Supported Capacity Configuration Lis
.IP "NVME_LOG_LID_FID_SUPPORTED_EFFECTS" 12
Feature Identifiers Supported and Effects
.IP "NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS" 12
NVMe-MI Commands Supported and Effects
.IP "NVME_LOG_LID_BOOT_PARTITION" 12
Boot Partition
.IP "NVME_LOG_LID_DISCOVER" 12
Discovery
.IP "NVME_LOG_LID_RESERVATION" 12
Reservation Notification
.IP "NVME_LOG_LID_SANITIZE" 12
Sanitize Status
.IP "NVME_LOG_LID_ZNS_CHANGED_ZONES" 12
Changed Zone List

View file

@ -0,0 +1,16 @@
.TH "libnvme" 9 "enum nvme_cmd_get_log_telemetry_host_lsp" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_cmd_get_log_telemetry_host_lsp \-
.SH SYNOPSIS
enum nvme_cmd_get_log_telemetry_host_lsp {
.br
.BI " NVME_LOG_TELEM_HOST_LSP_RETAIN"
,
.br
.br
.BI " NVME_LOG_TELEM_HOST_LSP_CREATE"
};
.SH Constants
.IP "NVME_LOG_TELEM_HOST_LSP_RETAIN" 12
.IP "NVME_LOG_TELEM_HOST_LSP_CREATE" 12

12
doc/man/nvme_compare.2 Normal file
View file

@ -0,0 +1,12 @@
.TH "nvme_compare" 9 "nvme_compare" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_compare \- Submit an nvme user compare command
.SH SYNOPSIS
.B "int" nvme_compare
.BI "(struct nvme_io_args *args " ");"
.SH ARGUMENTS
.IP "args" 12
\fIstruct nvme_io_args\fP argument structure
.SH "RETURN"
The nvme command status if a response was received (see
\fIenum nvme_status_field\fP) or -1 with errno set otherwise.

View file

@ -0,0 +1,78 @@
.TH "libnvme" 9 "enum nvme_connect_err" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_connect_err \- nvme connect error codes
.SH SYNOPSIS
enum nvme_connect_err {
.br
.BI " ENVME_CONNECT_RESOLVE"
,
.br
.br
.BI " ENVME_CONNECT_ADDRFAM"
,
.br
.br
.BI " ENVME_CONNECT_TRADDR"
,
.br
.br
.BI " ENVME_CONNECT_TARG"
,
.br
.br
.BI " ENVME_CONNECT_AARG"
,
.br
.br
.BI " ENVME_CONNECT_OPEN"
,
.br
.br
.BI " ENVME_CONNECT_WRITE"
,
.br
.br
.BI " ENVME_CONNECT_READ"
,
.br
.br
.BI " ENVME_CONNECT_PARSE"
,
.br
.br
.BI " ENVME_CONNECT_INVAL_TR"
,
.br
.br
.BI " ENVME_CONNECT_LOOKUP_SUBSYS_NAME"
,
.br
.br
.BI " ENVME_CONNECT_LOOKUP_SUBSYS"
};
.SH Constants
.IP "ENVME_CONNECT_RESOLVE" 12
failed to resolve host
.IP "ENVME_CONNECT_ADDRFAM" 12
unrecognized address family
.IP "ENVME_CONNECT_TRADDR" 12
failed to get traddr
.IP "ENVME_CONNECT_TARG" 12
need a transport (-t) argument
.IP "ENVME_CONNECT_AARG" 12
need a address (-a) argument
.IP "ENVME_CONNECT_OPEN" 12
failed to open nvme-fabrics device
.IP "ENVME_CONNECT_WRITE" 12
failed to write to nvme-fabrics device
.IP "ENVME_CONNECT_READ" 12
failed to read from nvme-fabrics device
.IP "ENVME_CONNECT_PARSE" 12
failed to parse ctrl info
.IP "ENVME_CONNECT_INVAL_TR" 12
invalid transport type
.IP "ENVME_CONNECT_LOOKUP_SUBSYS_NAME" 12
failed to lookup subsystem name
.IP "ENVME_CONNECT_LOOKUP_SUBSYS" 12
failed to lookup subsystem

199
doc/man/nvme_constants.2 Normal file
View file

@ -0,0 +1,199 @@
.TH "libnvme" 9 "enum nvme_constants" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_constants \- A place to stash various constant nvme values
.SH SYNOPSIS
enum nvme_constants {
.br
.BI " NVME_NSID_ALL"
,
.br
.br
.BI " NVME_NSID_NONE"
,
.br
.br
.BI " NVME_UUID_NONE"
,
.br
.br
.BI " NVME_CNTLID_NONE"
,
.br
.br
.BI " NVME_CNSSPECID_NONE"
,
.br
.br
.BI " NVME_LOG_LSP_NONE"
,
.br
.br
.BI " NVME_LOG_LSI_NONE"
,
.br
.br
.BI " NVME_LOG_LPO_NONE"
,
.br
.br
.BI " NVME_IDENTIFY_DATA_SIZE"
,
.br
.br
.BI " NVME_LOG_SUPPORTED_LOG_PAGES_MAX"
,
.br
.br
.BI " NVME_ID_NVMSET_LIST_MAX"
,
.br
.br
.BI " NVME_ID_UUID_LIST_MAX"
,
.br
.br
.BI " NVME_ID_CTRL_LIST_MAX"
,
.br
.br
.BI " NVME_ID_NS_LIST_MAX"
,
.br
.br
.BI " NVME_ID_SECONDARY_CTRL_MAX"
,
.br
.br
.BI " NVME_ID_DOMAIN_LIST_MAX"
,
.br
.br
.BI " NVME_ID_ENDURANCE_GROUP_LIST_MAX"
,
.br
.br
.BI " NVME_ID_ND_DESCRIPTOR_MAX"
,
.br
.br
.BI " NVME_FEAT_LBA_RANGE_MAX"
,
.br
.br
.BI " NVME_LOG_ST_MAX_RESULTS"
,
.br
.br
.BI " NVME_LOG_TELEM_BLOCK_SIZE"
,
.br
.br
.BI " NVME_LOG_FID_SUPPORTED_EFFECTS_MAX"
,
.br
.br
.BI " NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_MAX"
,
.br
.br
.BI " NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_RESERVED"
,
.br
.br
.BI " NVME_DSM_MAX_RANGES"
,
.br
.br
.BI " NVME_NQN_LENGTH"
,
.br
.br
.BI " NVMF_TRADDR_SIZE"
,
.br
.br
.BI " NVMF_TSAS_SIZE"
,
.br
.br
.BI " NVME_ZNS_CHANGED_ZONES_MAX"
};
.SH Constants
.IP "NVME_NSID_ALL" 12
A broadcast value that is used to specify all
namespaces
.IP "NVME_NSID_NONE" 12
The invalid namespace id, for when the nsid
parameter is not used in a command
.IP "NVME_UUID_NONE" 12
Use to omit a uuid command parameter
.IP "NVME_CNTLID_NONE" 12
Use to omit a cntlid command parameter
.IP "NVME_CNSSPECID_NONE" 12
Use to omit a cns_specific_id command parameter
.IP "NVME_LOG_LSP_NONE" 12
Use to omit a log lsp command parameter
.IP "NVME_LOG_LSI_NONE" 12
Use to omit a log lsi command parameter
.IP "NVME_LOG_LPO_NONE" 12
Use to omit a log lpo command parameter
.IP "NVME_IDENTIFY_DATA_SIZE" 12
The transfer size for nvme identify commands
.IP "NVME_LOG_SUPPORTED_LOG_PAGES_MAX" 12
The lagest possible index in the supported
log pages log.
.IP "NVME_ID_NVMSET_LIST_MAX" 12
The largest possible nvmset index in identify
nvmeset
.IP "NVME_ID_UUID_LIST_MAX" 12
The largest possible uuid index in identify
uuid list
.IP "NVME_ID_CTRL_LIST_MAX" 12
The largest possible controller index in
identify controller list
.IP "NVME_ID_NS_LIST_MAX" 12
The largest possible namespace index in
identify namespace list
.IP "NVME_ID_SECONDARY_CTRL_MAX" 12
The largest possible secondary controller index
in identify secondary controller
.IP "NVME_ID_DOMAIN_LIST_MAX" 12
The largest possible domain index in the
in domain list
.IP "NVME_ID_ENDURANCE_GROUP_LIST_MAX" 12
The largest possible endurance group
index in the endurance group list
.IP "NVME_ID_ND_DESCRIPTOR_MAX" 12
The largest possible namespace granularity
index in the namespace granularity descriptor
list
.IP "NVME_FEAT_LBA_RANGE_MAX" 12
The largest possible LBA range index in feature
lba range type
.IP "NVME_LOG_ST_MAX_RESULTS" 12
The largest possible self test result index in the
device self test log
.IP "NVME_LOG_TELEM_BLOCK_SIZE" 12
Specification defined size of Telemetry Data Blocks
.IP "NVME_LOG_FID_SUPPORTED_EFFECTS_MAX" 12
The largest possible FID index in the
feature identifiers effects log.
.IP "NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_MAX" 12
The largest possible MI Command index
in the MI Command effects log.
.IP "NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_RESERVED" 12
The reserved space in the MI Command
effects log.
.IP "NVME_DSM_MAX_RANGES" 12
The largest possible range index in a data-set
management command
.IP "NVME_NQN_LENGTH" 12
Max length for NVMe Qualified Name
.IP "NVMF_TRADDR_SIZE" 12
Max Transport Address size
.IP "NVMF_TSAS_SIZE" 12
Max Transport Specific Address Subtype size
.IP "NVME_ZNS_CHANGED_ZONES_MAX" 12
Max number of zones in the changed zones log
page

12
doc/man/nvme_copy.2 Normal file
View file

@ -0,0 +1,12 @@
.TH "nvme_copy" 9 "nvme_copy" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_copy \-
.SH SYNOPSIS
.B "int" nvme_copy
.BI "(struct nvme_copy_args *args " ");"
.SH ARGUMENTS
.IP "args" 12
\fIstruct nvme_copy_args\fP argument structure
.SH "RETURN"
The nvme command status if a response was received (see
\fIenum nvme_status_field\fP) or -1 with errno set otherwise.

83
doc/man/nvme_copy_args.2 Normal file
View file

@ -0,0 +1,83 @@
.TH "libnvme" 9 "struct nvme_copy_args" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_copy_args \- Arguments for the NVMe Copy command
.SH SYNOPSIS
struct nvme_copy_args {
.br
.BI " __u64 sdlba;"
.br
.BI " __u32 *result;"
.br
.BI " struct nvme_copy_range *copy;"
.br
.BI " int args_size;"
.br
.BI " int fd;"
.br
.BI " __u32 timeout;"
.br
.BI " __u32 nsid;"
.br
.BI " __u32 ilbrt;"
.br
.BI " int lr;"
.br
.BI " int fua;"
.br
.BI " __u16 nr;"
.br
.BI " __u16 dspec;"
.br
.BI " __u16 lbatm;"
.br
.BI " __u16 lbat;"
.br
.BI " __u8 prinfor;"
.br
.BI " __u8 prinfow;"
.br
.BI " __u8 dtype;"
.br
.BI " __u8 format;"
.br
.BI "
};
.br
.SH Members
.IP "sdlba" 12
Start destination LBA
.IP "result" 12
The command completion result from CQE dword0
.IP "copy" 12
Range descriptior
.IP "args_size" 12
Size of \fIstruct nvme_copy_args\fP
.IP "fd" 12
File descriptor of the nvme device
.IP "timeout" 12
Timeout in ms
.IP "nsid" 12
Namespace identifier
.IP "ilbrt" 12
Initial logical block reference tag
.IP "lr" 12
Limited retry
.IP "fua" 12
Force unit access
.IP "nr" 12
Number of ranges
.IP "dspec" 12
Directive specific value
.IP "lbatm" 12
Logical block application tag mask
.IP "lbat" 12
Logical block application tag
.IP "prinfor" 12
Protection information field for read
.IP "prinfow" 12
Protection information field for write
.IP "dtype" 12
Directive type
.IP "format" 12
Descriptor format

39
doc/man/nvme_copy_range.2 Normal file
View file

@ -0,0 +1,39 @@
.TH "libnvme" 9 "struct nvme_copy_range" "April 2022" "API Manual" LINUX
.SH NAME
struct nvme_copy_range \-
.SH SYNOPSIS
struct nvme_copy_range {
.br
.BI " __u8 rsvd0[8];"
.br
.BI " __le64 slba;"
.br
.BI " __le16 nlb;"
.br
.BI " __u8 rsvd18[6];"
.br
.BI " __le32 eilbrt;"
.br
.BI " __le16 elbatm;"
.br
.BI " __le16 elbat;"
.br
.BI "
};
.br
.SH Members
.IP "rsvd0" 12
Reserved
.IP "slba" 12
Starting LBA
.IP "nlb" 12
Number of Logical Blocks
.IP "rsvd18" 12
Reserved
.IP "eilbrt" 12
Expected Initial Logical Block Reference Tag
.IP "elbatm" 12
Expected Logical Block Application Tag Mask
.IP "elbat" 12
Expected Logical Block Application Tag

View file

@ -0,0 +1,31 @@
.TH "nvme_create_ctrl" 9 "nvme_create_ctrl" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_create_ctrl \- Allocate an unconnected NVMe controller
.SH SYNOPSIS
.B "nvme_ctrl_t" nvme_create_ctrl
.BI "(nvme_root_t r " ","
.BI "const char *subsysnqn " ","
.BI "const char *transport " ","
.BI "const char *traddr " ","
.BI "const char *host_traddr " ","
.BI "const char *host_iface " ","
.BI "const char *trsvcid " ");"
.SH ARGUMENTS
.IP "r" 12
NVMe root element
.IP "subsysnqn" 12
Subsystem NQN
.IP "transport" 12
Transport type
.IP "traddr" 12
Transport address
.IP "host_traddr" 12
Host transport address
.IP "host_iface" 12
Host interface name
.IP "trsvcid" 12
Transport service ID
.SH "DESCRIPTION"
Creates an unconnected controller to be used for \fBnvme_add_ctrl\fP.
.SH "RETURN"
Controller instance

View file

@ -0,0 +1,14 @@
.TH "nvme_create_root" 9 "nvme_create_root" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_create_root \- Initialize root object
.SH SYNOPSIS
.B "nvme_root_t" nvme_create_root
.BI "(FILE *fp " ","
.BI "int log_level " ");"
.SH ARGUMENTS
.IP "fp" 12
File descriptor for logging messages
.IP "log_level" 12
Logging level to use
.SH "RETURN"
Initialized \fInvme_root_t\fP object

24
doc/man/nvme_csi.2 Normal file
View file

@ -0,0 +1,24 @@
.TH "libnvme" 9 "enum nvme_csi" "April 2022" "API Manual" LINUX
.SH NAME
enum nvme_csi \- Defined command set indicators
.SH SYNOPSIS
enum nvme_csi {
.br
.BI " NVME_CSI_NVM"
,
.br
.br
.BI " NVME_CSI_KV"
,
.br
.br
.BI " NVME_CSI_ZNS"
};
.SH Constants
.IP "NVME_CSI_NVM" 12
NVM Command Set Indicator
.IP "NVME_CSI_KV" 12
Key Value Command Set
.IP "NVME_CSI_ZNS" 12
Zoned Namespace Command Set

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_first_ns" 9 "nvme_ctrl_first_ns" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_first_ns \- Start namespace iterator
.SH SYNOPSIS
.B "nvme_ns_t" nvme_ctrl_first_ns
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
First \fInvme_ns_t\fP object of an \fIc\fP iterator

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_first_path" 9 "nvme_ctrl_first_path" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_first_path \- Start path iterator
.SH SYNOPSIS
.B "nvme_path_t" nvme_ctrl_first_path
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
First \fInvme_path_t\fP object of an \fIc\fP iterator

View file

@ -0,0 +1,12 @@
.TH "nvme_ctrl_for_each_ns" 9 "nvme_ctrl_for_each_ns" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_for_each_ns \- Traverse namespaces
.SH SYNOPSIS
.B "nvme_ctrl_for_each_ns
.BI "(c " ","
.BI "n " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.IP "n" 12
\fInvme_ns_t\fP object

View file

@ -0,0 +1,15 @@
.TH "nvme_ctrl_for_each_ns_safe" 9 "nvme_ctrl_for_each_ns_safe" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_for_each_ns_safe \- Traverse namespaces
.SH SYNOPSIS
.B "nvme_ctrl_for_each_ns_safe
.BI "(c " ","
.BI "n " ","
.BI "_n " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.IP "n" 12
\fInvme_ns_t\fP object
.IP "_n" 12
A \fInvme_ns_t_node\fP to use as temporary storage

View file

@ -0,0 +1,12 @@
.TH "nvme_ctrl_for_each_path" 9 "nvme_ctrl_for_each_path" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_for_each_path \- Traverse paths
.SH SYNOPSIS
.B "nvme_ctrl_for_each_path
.BI "(c " ","
.BI "p " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.IP "p" 12
\fInvme_path_t\fP object

View file

@ -0,0 +1,15 @@
.TH "nvme_ctrl_for_each_path_safe" 9 "nvme_ctrl_for_each_path_safe" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_for_each_path_safe \- Traverse paths
.SH SYNOPSIS
.B "nvme_ctrl_for_each_path_safe
.BI "(c " ","
.BI "p " ","
.BI "_p " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.IP "p" 12
\fInvme_path_t\fP object
.IP "_p" 12
A \fInvme_path_t_node\fP to use as temporary storage

View file

@ -0,0 +1,12 @@
.TH "nvme_ctrl_get_address" 9 "nvme_ctrl_get_address" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_address \- Address string of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_address
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
NVMe-over-Fabrics address string of \fIc\fP or empty string
of no address is present.

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_config" 9 "nvme_ctrl_get_config" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_config \- Fabrics configuration of a controller
.SH SYNOPSIS
.B "struct nvme_fabrics_config *" nvme_ctrl_get_config
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
Fabrics configuration of \fIc\fP

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_dhchap_key" 9 "nvme_ctrl_get_dhchap_key" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_dhchap_key \- Return controller key
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_dhchap_key
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller for which the key should be set
.SH "RETURN"
DH-HMAC-CHAP controller key or NULL if not set

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_fd" 9 "nvme_ctrl_get_fd" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_fd \- Get associated file descriptor
.SH SYNOPSIS
.B "int" nvme_ctrl_get_fd
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
File descriptor associated with \fIc\fP or -1

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_firmware" 9 "nvme_ctrl_get_firmware" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_firmware \- Firmware string of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_firmware
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
Firmware string of \fIc\fP

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_host_iface" 9 "nvme_ctrl_get_host_iface" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_host_iface \- Host interface name of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_host_iface
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
Host interface name of \fIc\fP (if present)

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_host_traddr" 9 "nvme_ctrl_get_host_traddr" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_host_traddr \- Host transport address of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_host_traddr
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
Host transport address of \fIc\fP (if present)

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_model" 9 "nvme_ctrl_get_model" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_model \- Model of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_model
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
Model string of \fIc\fP

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_name" 9 "nvme_ctrl_get_name" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_name \- sysfs name of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_name
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
sysfs name of \fIc\fP

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_numa_node" 9 "nvme_ctrl_get_numa_node" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_numa_node \- NUMA node of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_numa_node
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
String indicating the NUMA node

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_queue_count" 9 "nvme_ctrl_get_queue_count" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_queue_count \- Queue count of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_queue_count
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Controller instance
.SH "RETURN"
Queue count of \fIc\fP

View file

@ -0,0 +1,11 @@
.TH "nvme_ctrl_get_serial" 9 "nvme_ctrl_get_serial" "April 2022" "libnvme API manual" LINUX
.SH NAME
nvme_ctrl_get_serial \- Serial number of a controller
.SH SYNOPSIS
.B "const char *" nvme_ctrl_get_serial
.BI "(nvme_ctrl_t c " ");"
.SH ARGUMENTS
.IP "c" 12
Conroller instance
.SH "RETURN"
Serial number string of \fIc\fP

Some files were not shown because too many files have changed in this diff Show more