diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/build.sh | 230 | ||||
-rw-r--r-- | scripts/gen-hostnqn.sh | 4 | ||||
-rwxr-xr-x | scripts/latency | 115 | ||||
-rwxr-xr-x | scripts/meson-vcs-tag.sh | 17 | ||||
-rwxr-xr-x | scripts/regress | 113 | ||||
-rwxr-xr-x | scripts/release.sh | 132 | ||||
-rwxr-xr-x | scripts/update-docs.sh | 17 |
7 files changed, 628 insertions, 0 deletions
diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..470f39a --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,230 @@ +#!/bin/bash +set -e + +usage() { + echo "Usage: build.sh [-b [release|debug]] " + echo " [-c [gcc|clang]]" + echo " [-m [meson|muon]" + echo " [config]" + echo "" + echo "CI build script." + echo "" + echo " -b [release]|debug build type" + echo " -c [gcc]|clang compiler to use" + echo " -m [meson]|muon use meson or muon" + echo " -t [arm]|ppc64le|s390x cross compile target" + echo "" + echo "configs with meson:" + echo " [default] default settings" + echo " fallback download all dependencies" + echo " and build them as shared libraries" + echo " cross use cross toolchain to build" + echo " coverage build coverage report" + echo " appimage build AppImage target" + echo "" + echo "configs with muon:" + echo " [default] minimal static build" +} + +BUILDTOOL=meson +MESON=meson +BUILDTYPE=release +CROSS_TARGET=arm +CC=${CC:-"gcc"} + +while getopts "b:c:m:t:" o; do + case "${o}" in + b) + BUILDTYPE="${OPTARG}" + ;; + c) + CC="${OPTARG}" + ;; + m) + BUILDTOOL="${OPTARG}" + ;; + t) + CROSS_TARGET="${OPTARG}" + ;; + *) + usage + exit 1 + ;; + esac +done +shift $((OPTIND-1)) + +CONFIG=${1:-"default"} + +cd "$(git rev-parse --show-toplevel)" || exit 1 + +BUILDDIR="$(pwd)/.build-ci" +TOOLDIR="$(pwd)/.build-tools" + +fn_exists() { declare -F "$1" > /dev/null; } + +config_meson_default() { + CC="${CC}" "${MESON}" setup \ + --werror \ + --buildtype="${BUILDTYPE}" \ + --force-fallback-for=libnvme \ + -Dlibnvme:werror=false \ + "${BUILDDIR}" +} + +config_meson_fallback() { + CC="${CC}" "${MESON}" setup \ + --werror \ + --buildtype="${BUILDTYPE}" \ + --wrap-mode=forcefallback \ + --default-library=both \ + -Dlibnvme:werror=false \ + -Dopenssl:werror=false \ + "${BUILDDIR}" +} + +config_meson_cross() { + CC="${CC}" "${MESON}" setup \ + --werror \ + --buildtype="${BUILDTYPE}" \ + --cross-file=.github/cross/ubuntu-cross-${CROSS_TARGET}.txt \ + --force-fallback-for=libnvme \ + -Dlibnvme:werror=false \ + -Dlibnvme:python=disabled \ + -Dlibnvme:openssl=disabled \ + "${BUILDDIR}" +} + +config_meson_coverage() { + CC="${CC}" "${MESON}" setup \ + --werror \ + --buildtype="${BUILDTYPE}" \ + --force-fallback-for=libnvme \ + -Dlibnvme:werror=false \ + -Db_coverage=true \ + "${BUILDDIR}" +} + +config_meson_appimage() { + CC="${CC}" "${MESON}" setup \ + --werror \ + --buildtype="${BUILDTYPE}" \ + --force-fallback-for=libnvme \ + --prefix=/usr \ + -Dlibnvme:werror=false \ + "${BUILDDIR}" +} + +build_meson() { + "${MESON}" compile \ + -C "${BUILDDIR}" +} + +test_meson() { + "${MESON}" test \ + -C "${BUILDDIR}" +} + +test_meson_coverage() { + "${MESON}" test \ + -C "${BUILDDIR}" + ninja -C "${BUILDDIR}" coverage --verbose +} + +install_meson_appimage() { + "${MESON}" install \ + -C "${BUILDDIR}" +} + +tools_build_samurai() { + if [ ! -d "${TOOLDIR}"/samurai ]; then + git clone --depth 1 https://github.com/michaelforney/samurai.git \ + "${TOOLDIR}/samurai" + fi + + if [[ -f "${TOOLDIR}/samurai/samu" ]]; then + return + fi + + pushd "${TOOLDIR}/samurai" || exit 1 + CC="${CC}" make + popd || exit 1 +} + +tools_build_muon() { + if [ ! -d "${TOOLDIR}/muon" ]; then + git clone --depth 1 https://git.sr.ht/~lattis/muon \ + "${TOOLDIR}/muon" + fi + + if [[ -f "${TOOLDIR}/build-muon/muon" ]]; then + return + fi + + pushd "${TOOLDIR}/muon" || exit 1 + + CC="${CC}" CFLAGS="${CFLAGS} -std=c99" ninja="${SAMU}" ./bootstrap.sh stage1 + + CC="${CC}" ninja="${SAMU}" stage1/muon setup \ + -Dprefix="${TOOLDIR}" \ + -Ddocs=disabled \ + -Dsamurai=disabled \ + -Dbestline=disabled \ + "${TOOLDIR}/build-muon" + "${SAMU}" -C "${TOOLDIR}/build-muon" + MUON="${BUILDDIR}/build-tools/.build-muon/muon" + + # "${TOOLDIR}/build-muon/muon" \ + # -C "${TOOLDIR}/build-muon" test + + popd || exit 1 +} + +config_muon_default() { + # wrap_mode=forcefallback depends on git being available + + CC="${CC}" CFLAGS="${CFLAGS}" ninja="${SAMU}" \ + "${MUON}" setup \ + -Ddefault_library=static \ + -Dc_link_args="-static" \ + -Dwrap_mode=forcefallback \ + -Dlibnvme:json-c=disabled \ + -Dlibnvme:python=disabled \ + -Dlibnvme:openssl=disabled \ + -Dlibnvme:keyutils=disabled \ + -Djson-c=disabled \ + "${BUILDDIR}" +} + +build_muon() { + "${SAMU}" -C "${BUILDDIR}" +} + +test_muon() { + ninja="${SAMU}" "${MUON}" -C "${BUILDDIR}" test + ldd "${BUILDDIR}/nvme" 2>&1 | grep 'not a dynamic executable' || exit 1 +} + +if [[ "${BUILDTOOL}" == "muon" ]]; then + SAMU="$(which samu 2> /dev/null)" || true + if [[ -z "${SAMU}" ]]; then + tools_build_samurai + SAMU="${TOOLDIR}/samurai/samu" + fi + + MUON="$(which muon 2> /dev/null)" || true + if [[ -z "${MUON}" ]]; then + tools_build_muon + MUON="${TOOLDIR}/build-muon/muon" + fi +fi + +echo "samu: ${SAMU}" +echo "muon: ${MUON}" + +rm -rf "${BUILDDIR}" + +config_"${BUILDTOOL}"_"${CONFIG}" +fn_exists "build_${BUILDTOOL}_${CONFIG}" && "build_${BUILDTOOL}_${CONFIG}" || build_"${BUILDTOOL}" +fn_exists "test_${BUILDTOOL}_${CONFIG}" && "test_${BUILDTOOL}_${CONFIG}" || test_"${BUILDTOOL}" +fn_exists "install_${BUILDTOOL}_${CONFIG}" && "install_${BUILDTOOL}_${CONFIG}" || true; diff --git a/scripts/gen-hostnqn.sh b/scripts/gen-hostnqn.sh new file mode 100644 index 0000000..b3edf14 --- /dev/null +++ b/scripts/gen-hostnqn.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later + +nvme gen-hostnqn diff --git a/scripts/latency b/scripts/latency new file mode 100755 index 0000000..0a8cc48 --- /dev/null +++ b/scripts/latency @@ -0,0 +1,115 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright 2015 PMC-Sierra, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# Author: Stephen Bates <stephen.bates@pmcs.com> +# +# Description: +# A shell script that calls the NVMe CLI multiple times to gather +# latency data. Consider this a poor man's iometer or fio for QD=1 +# analysis. Of course this is below the file-system and block +# layer so is a best case measurement. +# + +DEVICE= +WRITE=false +COUNT=10 +DATA_SIZE=4096 +METADATA_SIZE=64 + +RAND_BASE=temp.rand +RAND_WFILE=${RAND_BASE}.write +RAND_RFILE=${RAND_BASE}.read +OUTPUT=latency.dat + +green=$(tput bold)$(tput setaf 2) +red=$(tput bold)$(tput setaf 1) +rst=$(tput sgr0) + +while getopts ":d:n:w" opt; do + case $opt in + d) + DEVICE=${OPTARG} + ;; + n) + COUNT=${OPTARG} + ;; + w) + echo "WARNING: Write mode enabled, this might trash your drive!" + WRITE=true + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +if [ "$COUNT" == "0" ]; then + echo "Count can not be 0" + exit 1 +fi + +if [ -z "$DEVICE" ]; then + echo "regress: You must specify a NVMe device using -d" + exit 1 +fi + +function run_test { + $* | grep -i latency >> ${OUTPUT} 2>&1 + if (( $? )); then + echo ${red}"FAILED!"${rst} + echo "Failed running command: " + echo " $*" + exit 1 + fi +} + +rm -f ${OUTPUT} > /dev/null || exit -1 +make clean > /dev/null || exit -1 +make install > /dev/null || exit -1 + +for i in `seq 1 ${COUNT}`; +do + if $WRITE ; then + dd if=/dev/urandom of=${RAND_WFILE} bs=${DATA_SIZE} count=1 + run_test nvme write ${DEVICE} --start-block=0 --block-count=0 \ + --metadata-size=${METADATA_SIZE} --data-size=${DATA_SIZE} \ + --data ${RAND_WFILE} --latency + rm ${RAND_WFILE} > /dev/null + else + run_test nvme read ${DEVICE} --start-block=0 --block-count=0 \ + --metadata-size=${METADATA_SIZE} --data-size=${DATA_SIZE} \ + --data ${RAND_RFILE} --latency + rm ${RAND_RFILE} > /dev/null + fi +done + +# Calculate average latency +SUM=0 +for i in `cat ${OUTPUT} | awk '{print $3}' | xargs` +do + SUM=$(($SUM + $i)) +done +AVERAGE=$(echo "scale=2; $SUM/$COUNT" | bc -l) +echo "Average Latency: $AVERAGE us" diff --git a/scripts/meson-vcs-tag.sh b/scripts/meson-vcs-tag.sh new file mode 100755 index 0000000..8ce6924 --- /dev/null +++ b/scripts/meson-vcs-tag.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later + +set -eu +set -o pipefail + +dir="${1:?}" +fallback="${2:?}" + +# Apparently git describe has a bug where it always considers the work-tree +# dirty when invoked with --git-dir (even though 'git status' is happy). Work +# around this issue by cd-ing to the source directory. +cd "$dir" +# Check that we have either .git/ (a normal clone) or a .git file (a work-tree) +# and that we don't get confused if a tarball is extracted in a higher-level +# git repository. +[ -e .git ] && git describe --abbrev=7 --dirty=+ 2>/dev/null | sed 's/^v//' || echo "$fallback" diff --git a/scripts/regress b/scripts/regress new file mode 100755 index 0000000..302ff86 --- /dev/null +++ b/scripts/regress @@ -0,0 +1,113 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright 2015 PMC-Sierra, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# Author: Stephen Bates <stephen.bates@pmcs.com> +# +# Description: +# Regression test-suite for the NVM Express CLI. +# + +DEVICE= +WRITE=false +LIST=false + +RAND_BASE=temp.rand +RAND_WFILE=${RAND_BASE}.write +RAND_RFILE=${RAND_BASE}.read +RAND_SIZE=4k + +green=$(tput bold)$(tput setaf 2) +red=$(tput bold)$(tput setaf 1) +rst=$(tput sgr0) + +while getopts ":d:wl" opt; do + case $opt in + d) + DEVICE=${OPTARG} + ;; + w) + echo "WARNING: Write mode enabled, this might trash your drive!" + WRITE=true + ;; + l) + LIST=true + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +if [ -z "$DEVICE" ]; then + echo "regress: You must specify a NVMe device using -d" + exit 1 +fi + +function print_pass_fail { + $* > /dev/null 2>&1 + if (( $? )); then + echo ${red}"FAILED!"${rst} + echo "Failed running command: " + echo " $*" + exit 1 + else + echo ${green}"PASSED!"${rst} + fi +} + +function run_test { + LINE="$*" + printf " %-3s %-68s : " "RUN" "${LINE::67}" + print_pass_fail $* +} + +make clean > /dev/null || exit -1 +make install > /dev/null || exit -1 + +if $LIST ; then + run_test nvme list +fi +run_test nvme id-ctrl ${DEVICE} +run_test nvme id-ns -raw-binary ${DEVICE} +run_test nvme list-ns -n 1 ${DEVICE} +run_test nvme get-ns-id ${DEVICE} +run_test nvme get-log ${DEVICE} --log-id=2 --log-len=512 +run_test nvme fw-log ${DEVICE} +run_test nvme fw-log ${DEVICE} -b +run_test nvme smart-log ${DEVICE} +run_test nvme error-log ${DEVICE} +run_test nvme get-feature ${DEVICE} -f 7 +run_test nvme flush ${DEVICE} + +if $WRITE ; then + run_test dd if=/dev/urandom of=${RAND_WFILE} bs=${RAND_SIZE} count=1 + run_test nvme write ${DEVICE} --start-block=0 --block-count=0 --data-size=${RAND_SIZE} --data ${RAND_WFILE} +fi +run_test nvme read ${DEVICE} --start-block=0 --block-count=0 --data-size=${RAND_SIZE} --data ${RAND_RFILE} --latency +if $WRITE ; then + run_test diff ${RAND_RFILE} ${RAND_WFILE} + rm ${RAND_WFILE} > /dev/null +fi +rm ${RAND_RFILE} > /dev/null diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..d2cbb08 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,132 @@ +#!/bin/bash + +usage() { + echo "Usage: release.sh [-d] VERSION" + echo "" + echo "The script does all necessary steps to create a new release." + echo "" + echo " -d: no documentation update" + echo " -n: dry run" + echo "" + echo "Note: The version number needs to be exactly" + echo " '^v[\d]+.[\d]+(.[\d\]+(-rc[0-9]+)?$'" + echo "" + echo "example:" + echo " release.sh v2.1-rc0 # v2.1 release candidate 0" + echo " release.sh v2.1 # v2.1 release" +} + +build_doc=true +dry_run=false + +while getopts "dn" o; do + case "${o}" in + d) + build_doc=false + ;; + n) + dry_run=true + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +VERSION=${1:-} + +if [ -z "$VERSION" ] ; then + usage + exit 1 +fi + +# expected version regex +re='^v([0-9]+\.[0-9]+(\.[0-9]+)?)(-rc[0-9]+)?$' + +# use the version string provided from the command line +if [[ "$VERSION" =~ ${re} ]]; then + echo "valid version $VERSION string" + + # remove the leading 'v' + ver="${VERSION#v}" +else + echo "invalid version string $VERSION" + exit 1 +fi + +cd "$(git rev-parse --show-toplevel)" || exit 1 + +if [[ -f subprojects/libnvme.wrap ]]; then + git -C subprojects/libnvme fetch --all + + # extract the version string from libnvme by using the ref + # defined in libnvme.wrap. + libnvme_ref=$(sed -n "s/revision = \([0-9a-z]\+\)/\1/p" subprojects/libnvme.wrap) + libnvme_VERSION=$(git -C subprojects/libnvme describe "${libnvme_ref}") + if [[ "${libnvme_VERSION}" =~ ${re} ]]; then + echo "libnvme: valid version ${libnvme_VERSION} string" + + # remove the leading 'v' + libnvme_ver="${libnvme_VERSION#v}" + else + echo "libnvme: invalid version string ${libnvme_VERSION}" + exit 1 + fi +fi + +if [[ -n $(git status -s) ]]; then + echo "tree is dirty." + if [[ "${dry_run}" = false ]]; then + exit 1 + fi +fi + +if [ "$(git rev-parse --abbrev-ref HEAD)" != "master" ] ; then + echo "currently not on master branch. abort." + exit 1 +fi + +# update all docs +doc_dir="" +if [ -d "Documentation" ]; then + doc_dir="Documentation" +elif [ -d "doc" ]; then + doc_dir="doc" +else + echo "documentation directory not found" + exit 1 +fi + +# update meson.build +sed -i -e "0,/[ \t]version: /s/\([ \t]version: \).*/\1\'$ver\',/" meson.build +if [[ -f subprojects/libnvme.wrap ]]; then + sed -i -e "s/\(dependency('libnvme', version: '>=\)\([\.1-9]\+\)/\1$libnvme_ver/" meson.build +fi + +if [[ "${dry_run}" = false ]]; then + git add meson.build + git commit -s -m "build: Update version to $VERSION" +fi + +if [ "$build_doc" = true ]; then + # update documentation + ./scripts/update-docs.sh + if [[ "${dry_run}" = false ]]; then + git add $doc_dir + git commit -s -m "doc: Regenerate all docs for $VERSION" + fi +fi + +if [[ "${dry_run}" = true ]]; then + exit 0 +fi + +git tag -s -m "Release $VERSION" "$VERSION" +git push --dry-run origin "$VERSION"^{}:master tag "$VERSION" + +read -p "All good? Ready to push changes to remote? [Yy]" -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + git push origin "$VERSION"^{}:master tag "$VERSION" +fi diff --git a/scripts/update-docs.sh b/scripts/update-docs.sh new file mode 100755 index 0000000..6fe1132 --- /dev/null +++ b/scripts/update-docs.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later + +cd "$(git rev-parse --show-toplevel)" || exit 1 + +BUILDDIR="$(mktemp -d)" +trap 'rm -rf -- $BUILDDIR' EXIT + +meson setup \ + -Ddocs=all \ + -Ddocs-build=true \ + --force-fallback-for=libnvme \ + "${BUILDDIR}" +meson compile -C "${BUILDDIR}" +find "${BUILDDIR}/Documentation" -maxdepth 1 \ + \( -name '*.1' -o -name '*.html' \) \ + -exec cp {} Documentation/ \; |