From b56da6b201d56a2120c4cd777f2008b817faf9aa Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Wed, 28 Dec 2022 16:13:50 +0000 Subject: [PATCH 01/10] Cleaned up docs/some code formatting, fixed spec for sles, updated changelog, copyright year and version to 9.0.0 --- .gitignore | 1 + CHANGELOG.md | 24 ++++ Makefile | 2 +- README.md | 4 +- conf/Makefile | 2 +- conf/rapiddisk.sh.pacemaker | 2 +- conf/rapiddisk.sh.rgmanager | 2 +- doc/Makefile | 2 +- doc/rapiddisk.1 | 3 + doc/rapiddiskd.1 | 5 +- module/Makefile | 4 +- module/dkms.conf | 2 +- module/rapiddisk-cache.c | 8 +- module/rapiddisk.c | 6 +- pkg/debian/changelog | 27 +++++ pkg/debian/copyright | 6 +- pkg/rpm/rapiddisk.spec.rhel | 29 ++++- pkg/rpm/rapiddisk.spec.sles | 115 +++++++++++++------ scripts/nvmet/nvmet-generate-hostnqn.sh | 2 +- scripts/nvmet/nvmet-tune-system.sh | 2 +- scripts/rapiddisk-legacy/rapiddisk-legacy.sh | 4 +- src/Makefile | 2 +- src/common.h | 31 +++-- src/json.c | 7 +- src/json.h | 6 +- src/main.c | 8 +- src/main.h | 40 +++---- src/net.c | 10 +- src/nvmet.c | 9 +- src/nvmet.h | 7 +- src/rapiddiskd.c | 12 +- src/rapiddiskd.h | 12 +- src/rdsk.c | 9 +- src/rdsk.h | 12 +- src/sys.c | 9 +- src/sys.h | 6 +- src/utils.c | 9 +- src/utils.h | 6 +- test/Makefile | 2 +- test/rxflush.c | 2 +- test/rxio.c | 2 +- test/rxioctl.c | 2 +- test/rxro.c | 2 +- 43 files changed, 304 insertions(+), 153 deletions(-) diff --git a/.gitignore b/.gitignore index 458ef0b..ef5ec0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.a *.o *.o.* +*.d *.mod *.mod.* *.ko diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5871d..c438c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ +### Release 9.0.0 ### +- module: Added code to capture page count metrics. +- module: Updated ioctl support. +- module: Fixed page alloc usage decrement on discard. +- module: Added shrink volume support. +- module: Added support for 5.19 Linux kernels (thank you Andrea Righi). +- module: Added support for 6.0 Linux kernels. +- utility: Added code to lock/unlock RAM device. +- utility: Added flag to suppress header in stdout (thank you Matteo Tenca). +- utility: Added support for RapidDisk "model" branding and support for revalidate size in NVMe Target logic. +- utility: Traced, found and fixed all discovered memory leaks (a huge undertaking, thank you Matteo Tenca!!!). +- utility: Rewrite daemon to execute commands from a shared library instead of popen to utility (another huge undertaking, thank you Matteo Tenca!!!). +- utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). +- utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). +- utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). +- scripts: Fixed error checking in NVMe Target hostnqn script file. +- scripts: Added fio execution script file examples. +- scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). +- build: Update Makefiles and add support for CPPFLAGS, CFLAGS, LDFLAGS, etc. (thank you Matteo Tenca). +- build: Update Debian and RPM packaging with updated depends (thank you Matteo Tenca). +- documentation: Added dm-writecache stats notes. +- documentation: Added contrib file and cleaned up README and man pages. +- documentation: Added doxygen documentation support (thank you Matteo Tenca). + ### Release 8.2.0 ### - module: Fixed support for 5.14. - documentation: Updated README files. diff --git a/Makefile b/Makefile index 53987bd..c67438c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Copyright © 2016 - 2022 Petros Koutoupis +# Copyright © 2016 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify diff --git a/README.md b/README.md index f0ecdc0..bb9276f 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,8 @@ An example of a POST command: Change into the project's parent directory path. > To build the rapiddisk management utility, you will need to have the -> `libjansson` and `libmicrohttpd` development library files installed -> on your host system. +> `libjansson`, `libpcre2-dev`, `libdevmapper` and `libmicrohttpd` +> development library files installed on your host system. > > You are required to having either the full kernel source or the kernel > headers installed for your current kernel revision. diff --git a/conf/Makefile b/conf/Makefile index 3129ff4..4c56045 100644 --- a/conf/Makefile +++ b/conf/Makefile @@ -1,4 +1,4 @@ -# Copyright © 2016 - 2022 Petros Koutoupis +# Copyright © 2016 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify diff --git a/conf/rapiddisk.sh.pacemaker b/conf/rapiddisk.sh.pacemaker index 68666cb..ca75b48 100755 --- a/conf/rapiddisk.sh.pacemaker +++ b/conf/rapiddisk.sh.pacemaker @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (C) 2015 - 2022 Petros Koutoupis. All rights reserved. +# Copyright (C) 2015 - 2023 Petros Koutoupis. All rights reserved. # PATH=/bin:/sbin:/usr/bin:/usr/sbin diff --git a/conf/rapiddisk.sh.rgmanager b/conf/rapiddisk.sh.rgmanager index cff2814..26ed3bf 100755 --- a/conf/rapiddisk.sh.rgmanager +++ b/conf/rapiddisk.sh.rgmanager @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (C) 2015 - 2022 Petros Koutoupis. All rights reserved. +# Copyright (C) 2015 - 2023 Petros Koutoupis. All rights reserved. # PATH=/bin:/sbin:/usr/bin:/usr/sbin diff --git a/doc/Makefile b/doc/Makefile index 12d9902..c623016 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,4 +1,4 @@ -# Copyright © 2016 - 2022 Petros Koutoupis +# Copyright © 2016 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify diff --git a/doc/rapiddisk.1 b/doc/rapiddisk.1 index 9918ca7..b6781af 100755 --- a/doc/rapiddisk.1 +++ b/doc/rapiddisk.1 @@ -63,6 +63,9 @@ The port to export / unexport the NVMe Target to / from. Define cache policy: write-through (wt), write-around (wa) or writeback (wb) (dangerous) (default: write-through). Writeback caching is supplied by the dm-writecache kernel module and is not intended for production use as it may result in data loss on hardware/power failure. .TP +-q +List all system memory and block device resources. +.TP -R Revalidate size of NVMe export using existing RapidDisk device. .TP diff --git a/doc/rapiddiskd.1 b/doc/rapiddiskd.1 index ca31c6c..b0024b8 100755 --- a/doc/rapiddiskd.1 +++ b/doc/rapiddiskd.1 @@ -7,6 +7,9 @@ rapiddiskd [ -h | -v ] [ options ] rapiddiskd is a daemon intended to listen for API requests to manage RapidDisk functions. .SS Options .TP +-d +Remain in the foreground (implies -V). +.TP -h Invoke the help menu. .TP @@ -14,7 +17,7 @@ Invoke the help menu. Change port to listen on (default: 9118). .TP -V -Enable debug messages to stdout (this is ugly) +Enable debug messages to stdout (this is ugly). .TP -v Display the version number. diff --git a/module/Makefile b/module/Makefile index 5dae267..39780de 100644 --- a/module/Makefile +++ b/module/Makefile @@ -1,4 +1,4 @@ -# Copyright © 2011 - 2022 Petros Koutoupis +# Copyright © 2011 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify @@ -15,7 +15,7 @@ # # SPDX-License-Identifier: GPL-2.0-only -VERSION = 8.2.0 +VERSION = 9.0.0 ifeq ($(KSRC),) KSRC := /lib/modules/$(shell uname -r)/build diff --git a/module/dkms.conf b/module/dkms.conf index 62f17bb..51adabf 100644 --- a/module/dkms.conf +++ b/module/dkms.conf @@ -1,5 +1,5 @@ PACKAGE_NAME="rapiddisk" -PACKAGE_VERSION="8.2.0" +PACKAGE_VERSION="9.0.0" BUILT_MODULE_NAME[0]="rapiddisk" BUILT_MODULE_NAME[1]="rapiddisk-cache" DEST_MODULE_LOCATION[0]="/kernel/rapiddisk/" diff --git a/module/rapiddisk-cache.c b/module/rapiddisk-cache.c index 978265c..0a6cf78 100644 --- a/module/rapiddisk-cache.c +++ b/module/rapiddisk-cache.c @@ -1,5 +1,5 @@ /******************************************************************************* - ** Copyright © 2011 - 2022 Petros Koutoupis + ** Copyright © 2011 - 2023 Petros Koutoupis ** All rights reserved. ** ** This program is free software: you can redistribute it and/or modify @@ -54,7 +54,7 @@ } \ } while (0) -#define VERSION_STR "8.2.0" +#define VERSION_STR "9.0.0" #define DM_MSG_PREFIX "rapiddisk-cache" #define READCACHE 1 @@ -1248,7 +1248,7 @@ cache_status(struct dm_target *ti, status_type_t type, unsigned status_flags, static struct target_type cache_target = { .name = "rapiddisk-cache", - .version = {8, 2, 0}, + .version = {9, 0, 0}, .module = THIS_MODULE, .ctr = cache_ctr, .dtr = cache_dtr, @@ -1290,4 +1290,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Petros Koutoupis "); MODULE_DESCRIPTION("RapidDisk-Cache DM target is a write-through caching target with RapidDisk volumes."); MODULE_VERSION(VERSION_STR); -MODULE_INFO(Copyright, "Copyright 2010 - 2022 Petros Koutoupis"); +MODULE_INFO(Copyright, "Copyright 2010 - 2023 Petros Koutoupis"); diff --git a/module/rapiddisk.c b/module/rapiddisk.c index 735aeda..dfb471c 100644 --- a/module/rapiddisk.c +++ b/module/rapiddisk.c @@ -1,5 +1,5 @@ /******************************************************************************* - ** Copyright © 2011 - 2022 Petros Koutoupis + ** Copyright © 2011 - 2023 Petros Koutoupis ** All rights reserved. ** ** This program is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ #include #include -#define VERSION_STR "8.2.0" +#define VERSION_STR "9.0.0" #define PREFIX "rapiddisk" #define BYTES_PER_SECTOR 512 #define MAX_RDSKS 1024 @@ -1021,4 +1021,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Petros Koutoupis "); MODULE_DESCRIPTION("RapidDisk is an enhanced RAM disk block device driver."); MODULE_VERSION(VERSION_STR); -MODULE_INFO(Copyright, "Copyright 2010 - 2022 Petros Koutoupis"); +MODULE_INFO(Copyright, "Copyright 2010 - 2023 Petros Koutoupis"); diff --git a/pkg/debian/changelog b/pkg/debian/changelog index 3f7d8cc..b9e4e87 100644 --- a/pkg/debian/changelog +++ b/pkg/debian/changelog @@ -1,3 +1,30 @@ +rapiddisk (9.0.0-1) UNRELEASED; urgency=medium + + * module: Added code to capture page count metrics. + * module: Updated ioctl support. + * module: Fixed page alloc usage decrement on discard. + * module: Added shrink volume support. + * module: Added support for 5.19 Linux kernels (thank you Andrea Righi). + * module: Added support for 6.0 Linux kernels. + * utility: Added code to lock/unlock RAM device. + * utility: Added flag to suppress header in stdout (thank you Matteo Tenca). + * utility: Added support for RapidDisk "model" branding and support for revalidate size in NVMe Target logic. + * utility: Traced, found and fixed all discovered memory leaks (a huge undertaking, thank you Matteo Tenca!!!). + * utility: Rewrite daemon to execute commands from a shared library instead of popen to utility (another huge undertaking, thank you Matteo Tenca!!!). + * utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). + * utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). + * utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). + * scripts: Fixed error checking in NVMe Target hostnqn script file. + * scripts: Added fio execution script file examples. + * scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). + * build: Update Makefiles and add support for CPPFLAGS, CFLAGS, LDFLAGS, etc. (thank you Matteo Tenca). + * build: Update Debian and RPM packaging with updated depends (thank you Matteo Tenca). + * documentation: Added dm-writecache stats notes. + * documentation: Added contrib file and cleaned up README and man pages. + * documentation: Added doxygen documentation support (thank you Matteo Tenca). + + -- Petros Koutoupis Wed, 28 Dec 2022 08:56:52 +0000 + rapiddisk (8.2.0-1) UNRELEASED; urgency=medium * module: Fixed support for 5.14. diff --git a/pkg/debian/copyright b/pkg/debian/copyright index b7a2e2c..c7c4335 100644 --- a/pkg/debian/copyright +++ b/pkg/debian/copyright @@ -4,15 +4,15 @@ Upstream-Contact: Petros Koutoupis Source: https://github.com/pkoutoupis/rapiddisk/ Files: * -Copyright: 2015-2022 Petros Koutoupis +Copyright: 2015-2023 Petros Koutoupis License: GPL-2.0+ Files: pkg/debian/* -Copyright: 2022 Matteo Tenca +Copyright: 2022-2023 Matteo Tenca License: GPL-2.0+ Files: scripts/rapiddisk-rootdev/* -Copyright: 2022 Matteo Tenca +Copyright: 2022-2023 Matteo Tenca License: GPL-2.0+ License: GPL-2.0+ diff --git a/pkg/rpm/rapiddisk.spec.rhel b/pkg/rpm/rapiddisk.spec.rhel index 6f2e2e6..514d9c0 100644 --- a/pkg/rpm/rapiddisk.spec.rhel +++ b/pkg/rpm/rapiddisk.spec.rhel @@ -1,6 +1,6 @@ Summary: The RapidDisk software defined advanced RAM drive and storage caching solution. Name: rapiddisk -Version: 8.2.0 +Version: 9.0.0 Release: 1 License: General Public License Version 2 Group: Applications/System @@ -29,6 +29,8 @@ configuration files, and command line utilities for managing RapidDisk enabled storage volumes and accessing them either locally or across an NVMe Target network. +%global debug_package %{nil} + %prep %setup -q @@ -105,6 +107,29 @@ rm -rf %{buildroot} %attr(0644,root,root) /usr/lib/systemd/system-preset/30-rapiddiskd.preset %changelog +* Wed Dec 28 2022 Petros Koutoupis +- module: Added code to capture page count metrics. +- module: Updated ioctl support. +- module: Fixed page alloc usage decrement on discard. +- module: Added shrink volume support. +- module: Added support for 5.19 Linux kernels (thank you Andrea Righi). +- module: Added support for 6.0 Linux kernels. +- utility: Added code to lock/unlock RAM device. +- utility: Added flag to suppress header in stdout (thank you Matteo Tenca). +- utility: Added support for RapidDisk "model" branding and support for revalidate size in NVMe Target logic. +- utility: Traced, found and fixed all discovered memory leaks (a huge undertaking, thank you Matteo Tenca!!!). +- utility: Rewrite daemon to execute commands from a shared library instead of popen to utility (another huge undertaking, thank you Matteo Tenca!!!). +- utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). +- utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). +- utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). +- scripts: Fixed error checking in NVMe Target hostnqn script file. +- scripts: Added fio execution script file examples. +- scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). +- build: Update Makefiles and add support for CPPFLAGS, CFLAGS, LDFLAGS, etc. (thank you Matteo Tenca). +- build: Update Debian and RPM packaging with updated depends (thank you Matteo Tenca). +- documentation: Added dm-writecache stats notes. +- documentation: Added contrib file and cleaned up README and man pages. +- documentation: Added doxygen documentation support (thank you Matteo Tenca). * Sat Jun 11 2022 Petros Koutoupis - module: Fixed support for 5.14. - documentation: Updated README files. @@ -169,7 +194,7 @@ rm -rf %{buildroot} - utility: Remove dm-crypt code; Not sure why i had it in the first place. Doesn't really belong. Just use cryptsetup. - utility: Removed archive/restore code and dependency on zlib. Again, can just use dd and tar. Is anyone even using this? - misc: Updated licensing and logo location (thanks Boian!). -* Mon May 25 2018 Petros Koutoupis +* Fri May 25 2018 Petros Koutoupis - kernel: added support for 4.17 kernel. - build: Cleaned up module clean Makefile. - Updated copyright years. diff --git a/pkg/rpm/rapiddisk.spec.sles b/pkg/rpm/rapiddisk.spec.sles index 2a05611..c13f1e1 100644 --- a/pkg/rpm/rapiddisk.spec.sles +++ b/pkg/rpm/rapiddisk.spec.sles @@ -1,13 +1,13 @@ Summary: The RapidDisk software defined advanced RAM drive and storage caching solution. Name: rapiddisk -Version: 8.2.0 +Version: 9.0.0 Release: 1 License: General Public License Version 2 Group: Applications/System Source: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root -Requires: gcc,make,kernel-headers,kernel-devel,dkms,libjansson4,libmicrohttpd12 -BuildRequires: kernel-headers,kernel-devel,gcc,make,libjansson-devel,libmicrohttpd-devel +Requires: gcc,make,kernel-headers,kernel-devel,dkms +BuildRequires: kernel-headers,kernel-devel,gcc,make %description The RapidDisk software defined advanced RAM drive and storage @@ -19,6 +19,8 @@ locally or across an NVMe Target network. %package utils Summary: The RapidDisk administration utilities. Group: Applications/System +Requires: rapiddisk,libjansson4,libmicrohttpd12,libpcre2-16-0,libpcre2-32-0,device-mapper +BuildRequires: gcc,make,libjansson-devel,libmicrohttpd-devel,pcre2-devel,device-mapper-devel,systemd %description utils The RapidDisk software defined advanced RAM drive and storage @@ -27,60 +29,107 @@ configuration files, and command line utilities for managing RapidDisk enabled storage volumes and accessing them either locally or across an NVMe Target network. +%global debug_package %{nil} + %prep -%setup -T -D -n rapiddisk +%setup -q %build -make +# invokes `make` into selected subdirs only +make -j -C src strip %install rm -rf %{buildroot} -cd src -make DESTDIR=%{buildroot}/ install +# no `make install` nor `make` needed here, since the modules will be compiled and +# put in place into the `post` section by `dkms` +# +# prepare the source directory for `dkms` with the proper files +mkdir -pv %{buildroot}/usr/src/rapiddisk-%{version} +cd module +cp -v dkms.conf %{buildroot}/usr/src/rapiddisk-%{version} +cp -v {rapiddisk,rapiddisk-cache}.c %{buildroot}/usr/src/rapiddisk-%{version} +cp -v Makefile %{buildroot}/usr/src/rapiddisk-%{version} + +# invokes `make install` into selected subdirs only +cd ../src +make -j DESTDIR=%{buildroot} install cd ../doc -make DESTDIR=%{buildroot}/ install +make -j DESTDIR=%{buildroot} install cd ../conf -make DESTDIR=%{buildroot}/ install -cd ../module -mkdir -pv %{buildroot}/usr/src/rapiddisk-%{version}/ -cp -v dkms.conf %{buildroot}/usr/src/rapiddisk-%{version}/ -cp -v {rapiddisk,rapiddisk-cache}.c %{buildroot}/usr/src/rapiddisk-%{version}/ -cp -v Makefile %{buildroot}/usr/src/rapiddisk-%{version}/ +install -D -m 755 -t %{buildroot}/etc/rapiddisk rapiddisk.sh.pacemaker rapiddisk.sh.rgmanager +install -D -m 644 -t %{buildroot}%{_unitdir} rapiddiskd.service +# creates the `etc/sysconfig/modules/rapiddisk.modules` file which loads the rapiddisk's modules on boot +mkdir -pv %{buildroot}/etc/sysconfig/modules +echo -ne "#!/bin/sh\nmodprobe rapiddisk max_sectors=2048 nr_requests=1024 2>&1 >/dev/null" > %{buildroot}/etc/sysconfig/modules/rapiddisk.modules +echo -e "\nmodprobe rapiddisk-cache 2>&1 >/dev/null" >> %{buildroot}/etc/sysconfig/modules/rapiddisk.modules +chmod +x %{buildroot}/etc/sysconfig/modules/rapiddisk.modules +mkdir -pv %{buildroot}/usr/lib/systemd/system-preset +echo "enable rapiddiskd.service" >%{buildroot}/usr/lib/systemd/system-preset/30-rapiddiskd.preset %post -dkms add -m rapiddisk -v %{version} -dkms build -m rapiddisk -v %{version} +# invokes dkms to add the source files installed in the `install` section. Note the `--rpm_safe_upgrade` option +dkms --rpm_safe_upgrade add -m rapiddisk -v %{version} +# invokes dkms to build and install the modules for the current kernel dkms install -m rapiddisk -v %{version} -echo rapiddisk > /etc/modules-load.d/rapiddisk.conf -echo rapiddisk-cache >> /etc/modules-load.d/rapiddisk.conf -chmod 755 /etc/modules-load.d/rapiddisk.conf -modprobe rapiddisk -modprobe rapiddisk-cache +# loads the modules +sh /etc/sysconfig/modules/rapiddisk.modules + +%post utils +%systemd_post rapiddiskd.service %preun -dkms remove -m rapiddisk -v %{version} --all +# note the `--rpm_safe_upgrade` option +dkms --rpm_safe_upgrade remove -m rapiddisk -v %{version} --all + +%preun utils +%systemd_preun rapiddiskd.service %postun -rm -f /lib/modules/$(uname -r)/{extra,updates,weak-updates}/{rapiddisk,rapiddisk-cache}.ko -rm -f /etc/modules-load.d/rapiddisk.conf + +%postun utils +%systemd_postun_with_restart rapiddiskd.service %clean rm -rf %{buildroot} %files %defattr(-,root,root) -/etc/* -/sbin/* /usr/src/rapiddisk-* +%attr(0755,root,root) /etc/sysconfig/modules/rapiddisk.modules %doc %attr(0444,root,root) /usr/share/man/man1/* %files utils %defattr(-,root,root) -/etc/* -/sbin/* -%doc %attr(0444,root,root) /usr/share/man/man1/* +%attr(0644,root,root) %{_unitdir}/rapiddiskd.service +%attr(0755,root,root) /etc/rapiddisk +%attr(0755,root,root) /sbin/rapiddisk +%attr(0755,root,root) /sbin/rapiddiskd +%attr(0644,root,root) /usr/lib/systemd/system-preset/30-rapiddiskd.preset %changelog +* Wed Dec 28 2022 Petros Koutoupis +- module: Added code to capture page count metrics. +- module: Updated ioctl support. +- module: Fixed page alloc usage decrement on discard. +- module: Added shrink volume support. +- module: Added support for 5.19 Linux kernels (thank you Andrea Righi). +- module: Added support for 6.0 Linux kernels. +- utility: Added code to lock/unlock RAM device. +- utility: Added flag to suppress header in stdout (thank you Matteo Tenca). +- utility: Added support for RapidDisk "model" branding and support for revalidate size in NVMe Target logic. +- utility: Traced, found and fixed all discovered memory leaks (a huge undertaking, thank you Matteo Tenca!!!). +- utility: Rewrite daemon to execute commands from a shared library instead of popen to utility (another huge undertaking, thank you Matteo Tenca!!!). +- utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). +- utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). +- utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). +- scripts: Fixed error checking in NVMe Target hostnqn script file. +- scripts: Added fio execution script file examples. +- scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). +- build: Update Makefiles and add support for CPPFLAGS, CFLAGS, LDFLAGS, etc. (thank you Matteo Tenca). +- build: Update Debian and RPM packaging with updated depends (thank you Matteo Tenca). +- documentation: Added dm-writecache stats notes. +- documentation: Added contrib file and cleaned up README and man pages. +- documentation: Added doxygen documentation support (thank you Matteo Tenca). * Sat Jun 11 2022 Petros Koutoupis - module: Fixed support for 5.14. - documentation: Updated README files. @@ -104,7 +153,7 @@ rm -rf %{buildroot} * Fri Dec 17 2021 Petros Koutoupis - module: Updated for 5.14 and 5.15 kernels - utility: Added NVMe Target support / framework -- utility: Added support for dm-writecache status readout in API (github issue #65) +- utility: Added support for dm-writecache status readout in API (github issue ##65) - utility: Module checker code now traverses via sysfs - utility: Added module checker in daemon - documentation: Clean up formatting and add content @@ -131,7 +180,7 @@ rm -rf %{buildroot} - utility: Restructured userspace CLI - test: Restructured and improved test framework - misc: Code / documentation cleanup -* Thu May 26 2020 Petros Koutoupis +* Tue May 26 2020 Petros Koutoupis - kernel: added support for 5.7 kernel - utility: fixed GCC compilation warnings - utility: code style cleanup @@ -145,7 +194,7 @@ rm -rf %{buildroot} - utility: Remove dm-crypt code; Not sure why i had it in the first place. Doesn't really belong. Just use cryptsetup. - utility: Removed archive/restore code and dependency on zlib. Again, can just use dd and tar. Is anyone even using this? - misc: Updated licensing and logo location (thanks Boian!). -* Mon May 25 2018 Petros Koutoupis +* Fri May 25 2018 Petros Koutoupis - kernel: added support for 4.17 kernel. - build: Cleaned up module clean Makefile. - Updated copyright years. @@ -179,7 +228,7 @@ rm -rf %{buildroot} * Mon May 9 2016 Petros Koutoupis - kernel: Refuse misaligned discard requests. - kernel: Convert ENOMEM to ENOSPC when cannot alloc pages. -- kernel: Added 4k physical block size attribute. +- kernel: Added 4k physical block size attribute * Fri Apr 22 2016 Petros Koutoupis - Code cleanup. - Also need to remove CONFIG_BLK_DEV_RAM_COUNT from distro specific packages. diff --git a/scripts/nvmet/nvmet-generate-hostnqn.sh b/scripts/nvmet/nvmet-generate-hostnqn.sh index 5956d0a..8a9e217 100644 --- a/scripts/nvmet/nvmet-generate-hostnqn.sh +++ b/scripts/nvmet/nvmet-generate-hostnqn.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright © 2021 - 2022 Petros Koutoupis +# Copyright © 2021 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify diff --git a/scripts/nvmet/nvmet-tune-system.sh b/scripts/nvmet/nvmet-tune-system.sh index c112966..5f1de6e 100644 --- a/scripts/nvmet/nvmet-tune-system.sh +++ b/scripts/nvmet/nvmet-tune-system.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright © 2021 - 2022 Petros Koutoupis +# Copyright © 2021 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify diff --git a/scripts/rapiddisk-legacy/rapiddisk-legacy.sh b/scripts/rapiddisk-legacy/rapiddisk-legacy.sh index 0df56f0..7ef00bd 100644 --- a/scripts/rapiddisk-legacy/rapiddisk-legacy.sh +++ b/scripts/rapiddisk-legacy/rapiddisk-legacy.sh @@ -8,8 +8,8 @@ fi ## usage ## function help_menu() { - echo -e "$1 8.2.0" - echo -e "Copyright 2011 - 2022 Petros Koutoupis" + echo -e "$1 9.0.0" + echo -e "Copyright 2011 - 2023 Petros Koutoupis" echo -e "" echo -e "$1 is an administration tool to manage the RapidDisk RAM disk devices and" echo -e "\tRapidDisk-Cache mappings." diff --git a/src/Makefile b/src/Makefile index 7ea7fdb..e68fb0e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -# Copyright © 2011 - 2022 Petros Koutoupis +# Copyright © 2011 - 2023 Petros Koutoupis # All rights reserved. # # This file is part of RapidDisk. diff --git a/src/common.h b/src/common.h index 2772d6b..14d3434 100644 --- a/src/common.h +++ b/src/common.h @@ -3,7 +3,7 @@ * @brief Common structure and value definitions * @details This header file defines constants and structures shared by the rapiddisk and the rapiddiskd source * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ #ifndef COMMON_H @@ -48,8 +48,8 @@ SPDX-License-Identifier: GPL-2.0-or-later #define PROCESS "rapiddisk" /** Rapiddiskd (daemon) Process name */ #define DAEMON PROCESS "d" -#define COPYRIGHT "Copyright 2011 - 2022 Petros Koutoupis" -#define VERSION_NUM "8.2.0" +#define COPYRIGHT "Copyright 2011 - 2023 Petros Koutoupis" +#define VERSION_NUM "9.0.0" #define SUCCESS 0 #define INVALID_VALUE -1 #define NAMELEN 0x200 @@ -65,14 +65,14 @@ typedef char bool; #define SYS_RDSK "/sys/kernel/rapiddisk/mgmt" #define SYS_MODULE "/sys/module" -#define FILEDATA 0x40 +#define FILEDATA 0x40 -#define NAMELEN 0x200 +#define NAMELEN 0x200 -#define DISABLED 0 -#define ENABLED 1 +#define DISABLED 0 +#define ENABLED 1 -#define ERR_CALLOC "%s: calloc: %s" +#define ERR_CALLOC "%s: calloc: %s" #define ERR_FLUSHING "Error flushing file descriptors: %s, %s." #define ERR_MALFORMED "Error: wrong number of arguments or malformed URL." #define ERR_INVALIDURL "Invalid URL" @@ -81,10 +81,10 @@ typedef char bool; #define ERR_UNSUPPORTED "Unsupported" #define ERR_INVALID_SIZE "Invalid size" #define ERR_NOTANUMBER "Not a number." -#define ERR_SCANDIR "%s: scandir: %s" -#define ERR_FOPEN "%s: fopen: %s, %s" -#define ERR_FREAD "%s: fread: %s, %s" -#define ERR_MODULES "%s, The needed modules are not loaded..." +#define ERR_SCANDIR "%s: scandir: %s" +#define ERR_FOPEN "%s: fopen: %s, %s" +#define ERR_FREAD "%s: fread: %s, %s" +#define ERR_MODULES "%s, The needed modules are not loaded..." #define ERR_ALREADY_RUNNING "%s, The daemon is already running..." #define ERR_NEW_MHD_DAEMON "Error creating MHD Daemon: %s, %s." #define ERR_SIGPIPE_HANDLER "Failed to install SIGPIPE handler: %s, %s" @@ -209,10 +209,9 @@ typedef struct NVMET_PORTS { struct NVMET_PORTS *next; } NVMET_PORTS; -typedef struct PTHREAD_ARGS { +typedef struct DAEMON_ARGS { bool verbose; char port[0xf]; - char path[NAMELEN]; -} PTHREAD_ARGS; +} DAEMON_ARGS; #endif diff --git a/src/json.c b/src/json.c index 7e170d1..afe9aff 100644 --- a/src/json.c +++ b/src/json.c @@ -1,6 +1,9 @@ /** + * @file json.c + * @brief JSON functions implementation + * @details This file contains all the JSON related functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ diff --git a/src/json.h b/src/json.h index fa134a6..8ceca04 100644 --- a/src/json.h +++ b/src/json.h @@ -1,9 +1,9 @@ /** - * @file + * @file json.h * @brief JSON function declarations * @details This header file declares some JSON related functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ diff --git a/src/main.c b/src/main.c index fe6d624..e918d9e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,9 @@ /** + * @file main.c + * @brief Main administration functions implementation + * @details This file contains all the functions related to the administration utility. * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ @@ -66,6 +69,7 @@ void online_menu(char *string) "\t\t\t(default: write-through). Writeback caching is supplied by the dm-writecache\n" "\t\t\tkernel module and is not intended for production use as it may result in data\n" "\t\t\tloss on hardware/power failure.\n" + "\t-q\t\tList all system memory and block device resources.\n" "\t-R\t\tRevalidate size of NVMe export using existing RapidDisk device.\n" "\t-r\t\tDynamically grow the size of an existing RapidDisk device.\n" "\t-s\t\tObtain RapidDisk-Cache Mappings statistics.\n" diff --git a/src/main.h b/src/main.h index 40eed72..eac0f8b 100644 --- a/src/main.h +++ b/src/main.h @@ -3,7 +3,7 @@ * @brief rapiddisk tool definitions * @details This header file defines some constants used by the rapiddisk tool * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,37 +26,37 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ #ifndef MAIN_H #define MAIN_H -#define ACTION_NONE 0x0 -#define ACTION_ATTACH 0x1 -#define ACTION_DETACH 0x2 -#define ACTION_FLUSH 0x3 -#define ACTION_LIST 0x4 -#define ACTION_CACHE_MAP 0x5 -#define ACTION_RESIZE 0x6 -#define ACTION_CACHE_STATS 0x7 -#define ACTION_CACHE_UNMAP 0x8 +#define ACTION_NONE 0x0 +#define ACTION_ATTACH 0x1 +#define ACTION_DETACH 0x2 +#define ACTION_FLUSH 0x3 +#define ACTION_LIST 0x4 +#define ACTION_CACHE_MAP 0x5 +#define ACTION_RESIZE 0x6 +#define ACTION_CACHE_STATS 0x7 +#define ACTION_CACHE_UNMAP 0x8 #define ACTION_QUERY_RESOURCES 0x9 #define ACTION_LIST_NVMET_PORTS 0xa -#define ACTION_LIST_NVMET 0xb +#define ACTION_LIST_NVMET 0xb #define ACTION_ENABLE_NVMET_PORT 0xc #define ACTION_DISABLE_NVMET_PORT 0xd -#define ACTION_EXPORT_NVMET 0xe +#define ACTION_EXPORT_NVMET 0xe #define ACTION_UNEXPORT_NVMET 0xf -#define ACTION_LOCK 0x10 -#define ACTION_UNLOCK 0x11 +#define ACTION_LOCK 0x10 +#define ACTION_UNLOCK 0x11 #define ACTION_REVALIDATE_NVMET_SIZE 0x12 -#define ERR_INVALID_ARG "Error. Invalid argument(s) or values entered." -#define ERR_NOWB_MODULE "Please ensure that the dm-writecache module is loaded and retry." -#define ERR_NO_DEVICES "Unable to locate any RapidDisk devices." -#define ERR_NO_MEMUSAGE "Error. Unable to retrieve memory usage data." -#define ERR_INVALID_PORT "Error. Invalid port number." +#define ERR_INVALID_ARG "Error. Invalid argument(s) or values entered." +#define ERR_NOWB_MODULE "Please ensure that the dm-writecache module is loaded and retry." +#define ERR_NO_DEVICES "Unable to locate any RapidDisk devices." +#define ERR_NO_MEMUSAGE "Error. Unable to retrieve memory usage data." +#define ERR_INVALID_PORT "Error. Invalid port number." #endif diff --git a/src/net.c b/src/net.c index 512a4ba..7a1b5ba 100644 --- a/src/net.c +++ b/src/net.c @@ -3,7 +3,7 @@ * @brief Daemon functions implementation * @details This file contains all the function related to the daemon * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ @@ -65,7 +65,7 @@ static int answer_to_connection(void *cls, struct MHD_Connection *connection, co struct RC_PROFILE *cache = NULL; struct VOLUME_PROFILE *volumes = NULL; struct MEM_PROFILE *mem = NULL; - struct PTHREAD_ARGS *args = (struct PTHREAD_ARGS *) cls; + struct DAEMON_ARGS *args = (struct DAEMON_ARGS *) cls; char *error_message = calloc(1, NAMELEN); char *split_arr[64] = {NULL}; char msg[NAMELEN] = {0}; @@ -681,7 +681,7 @@ static void signal_handler(int sig) { /** * Installs the SIGPIPE signal catcher */ -static void ignore_sigpipe (PTHREAD_ARGS *args) { +static void ignore_sigpipe (DAEMON_ARGS *args) { struct sigaction oldsig; struct sigaction sig; char msg[NAMELEN] = {0}; @@ -724,7 +724,7 @@ static void catch_exit_signals() { */ int mgmt_thread(void *arg) { - struct PTHREAD_ARGS *args = (struct PTHREAD_ARGS *)arg; + struct DAEMON_ARGS *args = (struct DAEMON_ARGS *)arg; struct MHD_Daemon *mydaemon = NULL; char msg[NAMELEN] = {0}; diff --git a/src/nvmet.c b/src/nvmet.c index 2d84f6d..916bef6 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -1,6 +1,9 @@ /** + * @file nvmet.c + * @brief NVME function definitions + * @details This file defines some NVME related functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ @@ -1286,4 +1289,4 @@ int nvmet_view_ports_json(char *error_message, char **json_result) { return rc; } -#endif \ No newline at end of file +#endif diff --git a/src/nvmet.h b/src/nvmet.h index 0c326bd..1a84ef1 100644 --- a/src/nvmet.h +++ b/src/nvmet.h @@ -1,9 +1,9 @@ /** - * @file + * @file nvmet.h * @brief NVME function declarations * @details This header file declares some NVME related functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ @@ -37,6 +37,7 @@ SPDX-License-Identifier: GPL-2.0-or-later #define XFER_MODE_TCP 0 #define XFER_MODE_RDMA 1 + struct NVMET_PROFILE *nvmet_scan_subsystem(char *return_message); struct NVMET_PORTS *nvmet_scan_ports(char *return_message); struct NVMET_PORTS *nvmet_scan_all_ports(char *return_message); diff --git a/src/rapiddiskd.c b/src/rapiddiskd.c index 44be502..57ece46 100644 --- a/src/rapiddiskd.c +++ b/src/rapiddiskd.c @@ -1,6 +1,6 @@ /** * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +23,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ @@ -40,11 +40,11 @@ void online_menu(void) printf("%s is a daemon intended to listen for API requests.\n\n" "Usage: %s [ -h | -v ] [ options ]\n\n", DAEMON, DAEMON); printf("Functions:\n" + "\t-d\tRemain in the foreground (implies -V).\n" "\t-h\tPrint this exact help menu.\n" "\t-p\tChange port to listen on (default: 9118).\n" "\t-V\tEnable debug messages to stderr (this is ugly).\n" - "\t-v\tPrint out version information.\n\n" - "\t-d\tRemain in foreground - implies -V.\n\n"); + "\t-v\tPrint out version information.\n\n"); } /* @@ -95,7 +95,7 @@ int main(int argc, char *argv[]) pid_t pid; int rc = SUCCESS, i; int stdin_f = -1, stdout_f = -1, stderr_f = -1; - struct PTHREAD_ARGS *args = NULL; + struct DAEMON_ARGS *args = NULL; bool verbose = FALSE, debug = FALSE; char port[6] = {0}; // max port is 65535 so 5 chars + 1 (NULL) char msg[NAMELEN] = {0}; @@ -320,7 +320,7 @@ int main(int argc, char *argv[]) } /* Allocating the args structure, this was moved after the fork to avoid duplicating/freeing it for every fork() */ - args = (struct PTHREAD_ARGS *)calloc(1, sizeof(struct PTHREAD_ARGS)); + args = (struct DAEMON_ARGS *)calloc(1, sizeof(struct DAEMON_ARGS)); if (args == NULL) { syslog(LOG_ERR|LOG_DAEMON, ERR_CALLOC, __func__, strerror(errno)); syslog(LOG_ERR|LOG_DAEMON, D_EXITING); diff --git a/src/rapiddiskd.h b/src/rapiddiskd.h index ea27aa8..584a04f 100644 --- a/src/rapiddiskd.h +++ b/src/rapiddiskd.h @@ -3,7 +3,7 @@ * @brief Daemon defines * @details This header file defines some constants used by the daemon * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ @@ -52,12 +52,12 @@ SPDX-License-Identifier: GPL-2.0-or-later #define CMD_LIST_NVMET "/v1/listAllNVMeTargets" #define CMD_LIST_NVMET_PORTS "/v1/listAllNVMePorts" -#define PID_FILE "/run/rapiddiskd.pid" +#define PID_FILE "/run/rapiddiskd.pid" #define D_STDERR_LOG "/tmp/rapiddiskd_err.log" #define D_STDOUT_LOG "/tmp/rapiddiskd_out.log" -#define D_EXITING "Daemon exiting." -#define D_STARTING "Starting daemon..." -#define D_RECV_REQ "Recevied request '%s'." +#define D_EXITING "Daemon exiting." +#define D_STARTING "Starting daemon..." +#define D_RECV_REQ "Recevied request '%s'." #define D_LOOP_EXITING "Daemon loop function exiting: %s." #define D_SIGNAL_RECEIVED "Signal_handler function, SIGNAL received: %s." diff --git a/src/rdsk.c b/src/rdsk.c index edc8d94..e48f228 100644 --- a/src/rdsk.c +++ b/src/rdsk.c @@ -1,6 +1,9 @@ /** + * @file rdsk.c + * @brief RapidDisk function definitions + * @details This file defines some RapidDisk related functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ @@ -145,7 +148,7 @@ char *read_info(char *name, char *string, char *return_message) } fclose(fp); len = strlen(buf); - strncpy(obuf, buf, (len - 1)); + strncpy(obuf, buf, (len - 1)); /* Do not copy tailing escape character */ sprintf(obuf, "%s", obuf); return obuf; diff --git a/src/rdsk.h b/src/rdsk.h index bb9eee0..eb3e781 100644 --- a/src/rdsk.h +++ b/src/rdsk.h @@ -3,7 +3,7 @@ * @brief Disk functions and constants * @details This header file defines constants and functions related to disk access * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ @@ -36,11 +36,11 @@ SPDX-License-Identifier: GPL-2.0-or-later #include "common.h" #define BYTES_PER_SECTOR 0x200 -#define SYS_BLOCK "/sys/block" -#define ETC_MTAB "/etc/mtab" -#define DEV_MAPPER "/dev/mapper" +#define SYS_BLOCK "/sys/block" +#define ETC_MTAB "/etc/mtab" +#define DEV_MAPPER "/dev/mapper" #define RD_GET_USAGE 0x0530 -#define PAGE_SIZE 0x1000 +#define PAGE_SIZE 0x1000 void print_error(char *format_string, char *return_message, ...); char *read_info(char *name, char *string, char *return_message); diff --git a/src/sys.c b/src/sys.c index 2407d55..3373742 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,6 +1,9 @@ /** + * @file sys.c + * @brief System function definitions + * @details This file contains all the system functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ @@ -185,4 +188,4 @@ int get_memory_usage(struct MEM_PROFILE *mem, char *return_message) mem->mem_total = si.totalram; mem->mem_free = si.freeram; return SUCCESS; -} \ No newline at end of file +} diff --git a/src/sys.h b/src/sys.h index 6a739f1..a63a3dd 100644 --- a/src/sys.h +++ b/src/sys.h @@ -1,9 +1,9 @@ /** - * @file + * @file sys.h * @brief System-related function definitions * @details This header file defines system-related functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ #ifndef SYS_H diff --git a/src/utils.c b/src/utils.c index 936a67c..7fab7c8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,6 +1,9 @@ /** + * @file util.c + * @brief Utility function definitions + * @details This file contains all the utility functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -23,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ -* @version 8.2.0 +* @version 9.0.0 * @date 26 September 2022 */ #include "utils.h" @@ -368,4 +371,4 @@ void print_message(int ret_value, char *message, bool json_flag) { } else { printf("%s\n", message); } -} \ No newline at end of file +} diff --git a/src/utils.h b/src/utils.h index 3916be1..8049267 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,9 +1,9 @@ /** - * @file + * @file utils.h * @brief Utility functions declarations * @details This header file defines some utility functions * @copyright @verbatim -Copyright © 2011 - 2022 Petros Koutoupis +Copyright © 2011 - 2023 Petros Koutoupis All rights reserved. @@ -26,7 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later @endverbatim * @author Petros Koutoupis \ * @author Matteo Tenca \ - * @version 8.2.0 + * @version 9.0.0 * @date 26 September 2022 */ #ifndef UTILS_H diff --git a/test/Makefile b/test/Makefile index 1b267f1..e6530a6 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,4 +1,4 @@ -# Copyright © 2016 - 2022 Petros Koutoupis +# Copyright © 2016 - 2023 Petros Koutoupis # All rights reserved. # # This program is free software: you can redistribute it and/or modify diff --git a/test/rxflush.c b/test/rxflush.c index deccf8c..27b93f4 100644 --- a/test/rxflush.c +++ b/test/rxflush.c @@ -1,6 +1,6 @@ /* rxflush.c */ -/** Copyright © 2016 - 2022 Petros Koutoupis +/** Copyright © 2016 - 2023 Petros Koutoupis ** All rights reserved. ** ** This program is free software: you can redistribute it and/or modify diff --git a/test/rxio.c b/test/rxio.c index 11aea24..3455158 100644 --- a/test/rxio.c +++ b/test/rxio.c @@ -1,6 +1,6 @@ /* rxio.c */ -/** Copyright © 2016 - 2022 Petros Koutoupis +/** Copyright © 2016 - 2023 Petros Koutoupis ** All rights reserved. ** ** This program is free software: you can redistribute it and/or modify diff --git a/test/rxioctl.c b/test/rxioctl.c index d06a870..97092d7 100644 --- a/test/rxioctl.c +++ b/test/rxioctl.c @@ -1,6 +1,6 @@ /* rxioctl.c */ -/** Copyright © 2016 - 2022 Petros Koutoupis +/** Copyright © 2016 - 2023 Petros Koutoupis ** All rights reserved. ** ** This program is free software: you can redistribute it and/or modify diff --git a/test/rxro.c b/test/rxro.c index aa2117b..7dd5b19 100644 --- a/test/rxro.c +++ b/test/rxro.c @@ -1,6 +1,6 @@ /* rxro.c */ -/** Copyright © 2016 - 2022 Petros Koutoupis +/** Copyright © 2016 - 2023 Petros Koutoupis ** All rights reserved. ** ** This program is free software: you can redistribute it and/or modify From a0346cddba1f4e802393419196c9b0bab7588f86 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Wed, 28 Dec 2022 17:18:37 +0000 Subject: [PATCH 02/10] Fix resize operation error messaging reported in issue #142. --- CHANGELOG.md | 1 + pkg/debian/changelog | 1 + pkg/rpm/rapiddisk.spec.rhel | 1 + pkg/rpm/rapiddisk.spec.sles | 1 + src/rdsk.c | 9 +++++++-- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c438c9e..4943627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). - utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). - utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). +- utility: Fix resize operation error messaging (github issue #142). - scripts: Fixed error checking in NVMe Target hostnqn script file. - scripts: Added fio execution script file examples. - scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/pkg/debian/changelog b/pkg/debian/changelog index b9e4e87..a1da527 100644 --- a/pkg/debian/changelog +++ b/pkg/debian/changelog @@ -14,6 +14,7 @@ rapiddisk (9.0.0-1) UNRELEASED; urgency=medium * utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). * utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). * utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). + * utility: Fix resize operation error messaging (github issue #142). * scripts: Fixed error checking in NVMe Target hostnqn script file. * scripts: Added fio execution script file examples. * scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/pkg/rpm/rapiddisk.spec.rhel b/pkg/rpm/rapiddisk.spec.rhel index 514d9c0..99c8573 100644 --- a/pkg/rpm/rapiddisk.spec.rhel +++ b/pkg/rpm/rapiddisk.spec.rhel @@ -122,6 +122,7 @@ rm -rf %{buildroot} - utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). - utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). - utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). +- utility: Fix resize operation error messaging (github issue #142). - scripts: Fixed error checking in NVMe Target hostnqn script file. - scripts: Added fio execution script file examples. - scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/pkg/rpm/rapiddisk.spec.sles b/pkg/rpm/rapiddisk.spec.sles index c13f1e1..e38ab1f 100644 --- a/pkg/rpm/rapiddisk.spec.sles +++ b/pkg/rpm/rapiddisk.spec.sles @@ -122,6 +122,7 @@ rm -rf %{buildroot} - utility: Added checks in URL parsing logic for REST API (thank you Matteo Tenca). - utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). - utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). +- utility: Fix resize operation error messaging (github issue #142). - scripts: Fixed error checking in NVMe Target hostnqn script file. - scripts: Added fio execution script file examples. - scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/src/rdsk.c b/src/rdsk.c index e48f228..cdcecd9 100644 --- a/src/rdsk.c +++ b/src/rdsk.c @@ -829,8 +829,13 @@ int mem_device_resize(struct RD_PROFILE *prof, char *string, unsigned long long close(fd); if ((((size * 1024 * 1024) / BYTES_PER_BLOCK) <= (max_sectors)) || ((size * 1024) == (rd_size / 1024))) { - msg = "Error. Please specify a size larger than %llu Mbytes"; - print_error(msg, return_message, (((max_sectors * BYTES_PER_BLOCK) / 1024) / 1024)); + if ((size * 1024) == (rd_size / 1024)) { + msg = "Error. Size is currently set to %llu Mbytes. Please specify a size larger than %llu Mbytes."; + print_error(msg, return_message, (rd_size / 1024) / 1024, (((max_sectors * BYTES_PER_BLOCK) / 1024) / 1024)); + } else { + msg = "Error. Please specify a size larger than %llu Mbytes."; + print_error(msg, return_message, (((max_sectors * BYTES_PER_BLOCK) / 1024) / 1024)); + } return -EINVAL; } From ce50d8f9e3c70ef6a6a294e2be3c6f53af9c1db6 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Wed, 28 Dec 2022 20:23:32 +0000 Subject: [PATCH 03/10] Fixed and cleaned up NVMe Target code. Also added comments for clarity. --- src/nvmet.c | 154 +++++++++++++++++----------------------------------- 1 file changed, 51 insertions(+), 103 deletions(-) diff --git a/src/nvmet.c b/src/nvmet.c index 916bef6..bc62fc0 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -538,37 +538,12 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d char hostname[0x40] = {0x0}, path[NAMELEN] = {0x0}, path2[NAMELEN] = {0x0}; struct dirent **list; char *msg; - NVMET_PROFILE *nvmet = NULL; - NVMET_PROFILE *nvmet_orig = NULL; char error_message[NAMELEN] = {0}; - char full_device_name[NAMELEN] = {0}; - nvmet = nvmet_scan_subsystem(error_message); - if ((nvmet == NULL) && (strlen(error_message) != 0)) { - msg = "%s"; - print_error(msg, return_message, error_message); - return INVALID_VALUE; - } - - nvmet_orig = nvmet; - - sprintf(full_device_name, "/dev/%s", device); - - while (nvmet != NULL) { - if (strcmp(full_device_name, nvmet->device) == SUCCESS) { - rc = SUCCESS; - break; - } - nvmet = nvmet->next; - } - - free_nvmet_linked_lists(NULL, nvmet_orig); - - if (rc == SUCCESS) { - msg = "Error: device %s already in use."; - print_error(msg, return_message, device); - return INVALID_VALUE; - } + /* + * We do not care if the device has already been exported. We will continue to go through + * the motions to add more host NQNs to export the target to. + */ /* Check to see if device exists */ while (rd_prof != NULL) { @@ -845,7 +820,7 @@ int nvmet_revalidate_size(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char */ int nvmet_unexport_volume(char *device, char *host, int port, char *return_message) { - int rc = INVALID_VALUE, n, err; + int rc = INVALID_VALUE, n, err, hostno = 0; FILE *fp; char hostname[0x40] = {0x0}, path[NAMELEN] = {0x0}; struct dirent **list; @@ -884,6 +859,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa return rc; } + /* Remove host NQN */ if (strlen(host) != 0) { sprintf(path, "%s/%s%s-%s/allowed_hosts/%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device, host); if (access(path, F_OK) == SUCCESS) { @@ -905,36 +881,31 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa /* If a host is defined without any port number, just remove and exit. */ if (port == INVALID_VALUE) return SUCCESS; - } else { - /* If no host is defined, remove all hosts */ - sprintf(path, "%s/%s%s-%s/allowed_hosts/", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((err = scandir(path, &list, NULL, NULL)) < 0) { - goto host_check_out; - } + } + + /* + * Grab number of entries in allowed_hosts directory. If more than zero still exist, we will not + * proceed with the rest + */ + sprintf(path, "%s/%s%s-%s/allowed_hosts/", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); + if ((err = scandir(path, &list, NULL, NULL)) < 0) { + msg = "Error. Unable to scan host exports directory for %s. %s: unlink: %s"; + print_error(msg, return_message, path, __func__, strerror(errno)); + return rc; + } + hostno = err; + if (err > 0) { for (n = 0; n < err; n++) { if (strncmp(list[n]->d_name, ".", 1) != SUCCESS) { - sprintf(path, "%s/%s%s-%s/allowed_hosts/%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device, list[n]->d_name); - if (access(path, F_OK) == SUCCESS) { - rc = unlink(path); - if (rc != SUCCESS) { - msg = "Error. Unable to remove hosts. %s: unlink: %s"; - print_error(msg, return_message, __func__, strerror(errno)); - list = clean_scandir(list, err); - return rc; - } - } + msg = "The target is still mapped to host NQN %s"; + print_error(msg, return_message, list[n]->d_name); } } - list = clean_scandir(list, err); - if (return_message == NULL) { - msg = "Block device %s has been unmapped from all NVMe Target hosts."; - print_error(msg, return_message, device); - } } + list = clean_scandir(list, err); -host_check_out: - - if (port != INVALID_VALUE) { + /* Remove NVMe Target interface port */ + if ((port != INVALID_VALUE) && (hostno == 0)) { sprintf(path, "%s/%d/subsystems/%s%s-%s", SYS_NVMET_PORTS, port, NQN_HDR_STR, hostname, device); if (access(path, F_OK) == SUCCESS) { rc = unlink(path); @@ -947,58 +918,36 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa msg = "Block device %s has been unmapped from NVMe Target port %d."; print_error(msg, return_message, device, port); } -// } else { -// msg = "%s: Port %d and / or export does not exist"; -// print_error(msg, return_message, __func__, port); -// return rc; - } - } else { - /* If no port is defined, unmap from all ports */ - sprintf(path, "%s", SYS_NVMET_PORTS); - if ((err = scandir(path, &list, NULL, NULL)) < 0) - goto port_check_out; - for (n = 0; n < err; n++) { - if (strncmp(list[n]->d_name, ".", 1) != SUCCESS) { - sprintf(path, "%s/%s/subsystems/%s%s-%s", SYS_NVMET_PORTS, list[n]->d_name, NQN_HDR_STR, hostname, device); - if (access(path, F_OK) == SUCCESS) { - rc = unlink(path); - if (rc != SUCCESS) { - msg = "Error. Unable to remove NQN from ports. %s: unlink: %s"; - print_error(msg, return_message, __func__, strerror(errno)); - list = clean_scandir(list, err); - return rc; - } - } - } - } - list = clean_scandir(list, err); - if (return_message == NULL) { - msg = "Block device %s has been unmapped from all NVMe Target ports."; - print_error(msg, return_message, device); + } else { + /* The NVMe Target interface port number that was defined does not exist on the system */ + msg = "%s: Port %d and / or export does not exist"; + print_error(msg, return_message, __func__, port); + return rc; } } -port_check_out: - - /* If a port and / or host are defined, just remove / unmap and exit. */ - - /* I changed this test from "((strlen(host) == 0) && (port == INVALID_VALUE))" - * because prevented the complete removal of the mapping + /* + * If there are no more allowed_hosts and the target is not being exported by the port, remove + * the target export from the entire subsystem. NOTE - we are not checking other ports (yet). + * This check will come in a future update. */ - -// if ((strlen(host) != 0) && (port != INVALID_VALUE)) { + if ((port != INVALID_VALUE) && (hostno == 0)) { if (access(path, F_OK) == SUCCESS) { - /* Disable volume */ - sprintf(path, "%s/%s%s-%s/namespaces/1/enable", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((fp = fopen(path, "w")) == NULL){ - msg = "Error. Unable to open namespace enable file %s. %s: fopen: %s"; - print_error(msg, return_message, path, __func__, strerror(errno)); - return INVALID_VALUE; - } - fprintf(fp, "0"); - fclose(fp); + msg = "Error. Target is still exported through the port: %s"; + print_error(msg, return_message, __func__, path); + return INVALID_VALUE; + } + /* Disable volume */ + sprintf(path, "%s/%s%s-%s/namespaces/1/enable", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); + if ((fp = fopen(path, "w")) == NULL){ + msg = "Error. Unable to open namespace enable file %s. %s: fopen: %s"; + print_error(msg, return_message, path, __func__, strerror(errno)); + return INVALID_VALUE; } + fprintf(fp, "0"); + fclose(fp); + /* Remove namespace */ sprintf(path, "%s/%s%s-%s/namespaces/1", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); if (access(path, F_OK) == SUCCESS) { if ((rc = rmdir(path)) != SUCCESS) { @@ -1017,10 +966,9 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa return rc; } } -// } - - msg = "Block device %s has been removed from the NVMe Target subsystem."; - print_error(msg, return_message, device); + msg = "Block device %s has been removed from the NVMe Target subsystem."; + print_error(msg, return_message, device); + } return SUCCESS; } From 5999eb00e75e49a06d22f843dab8ea98c00ea804 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Thu, 29 Dec 2022 16:35:20 +0000 Subject: [PATCH 04/10] Cleaning up messaging. --- src/common.h | 10 ++++++---- src/main.c | 2 +- src/nvmet.c | 24 +++++++++++------------- src/rdsk.c | 46 ++++++++++++++++++---------------------------- 4 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/common.h b/src/common.h index 14d3434..7107fbd 100644 --- a/src/common.h +++ b/src/common.h @@ -75,11 +75,11 @@ typedef char bool; #define ERR_CALLOC "%s: calloc: %s" #define ERR_FLUSHING "Error flushing file descriptors: %s, %s." #define ERR_MALFORMED "Error: wrong number of arguments or malformed URL." -#define ERR_INVALIDURL "Invalid URL" +#define ERR_INVALIDURL "Invalid URL." #define ERR_INVALIDDEVNAME "Invalid device name." -#define ERR_DEV_STATUS "Can't get device status" -#define ERR_UNSUPPORTED "Unsupported" -#define ERR_INVALID_SIZE "Invalid size" +#define ERR_DEV_STATUS "Can't get device status." +#define ERR_UNSUPPORTED "Unsupported." +#define ERR_INVALID_SIZE "Invalid size." #define ERR_NOTANUMBER "Not a number." #define ERR_SCANDIR "%s: scandir: %s" #define ERR_FOPEN "%s: fopen: %s, %s" @@ -89,6 +89,8 @@ typedef char bool; #define ERR_NEW_MHD_DAEMON "Error creating MHD Daemon: %s, %s." #define ERR_SIGPIPE_HANDLER "Failed to install SIGPIPE handler: %s, %s" #define ERR_INVALID_MODE "Invalid cache mode in URL." +#define ERR_DEV_NOEXIST "Error. Device %s does not exist." +#define ERR_CACHE_TGT_NOEXIST "Error. Cache target %s does not exist." /** * For RapidDisk device list diff --git a/src/main.c b/src/main.c index e918d9e..bbaa3dd 100644 --- a/src/main.c +++ b/src/main.c @@ -497,7 +497,7 @@ int main(int argc, char *argv[]) /* This preprocessor if/endif is useful when the debbugger can't run as root */ #ifndef DEBUG if (geteuid() != 0) { - printf("\nYou must be root or contain sudo permissions to initiate this\n\n"); + printf("\nYou must be root or contain sudo permissions to initiate this.\n\n"); return -EACCES; } #endif diff --git a/src/nvmet.c b/src/nvmet.c index bc62fc0..f91e3ab 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -563,8 +563,7 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, device); + print_error(ERR_DEV_NOEXIST, return_message, device); return INVALID_VALUE; } @@ -721,7 +720,7 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d } sprintf(path, "port %d", port); - msg = "Block device %s has been mapped to %s through %s as %s%s-%s"; + msg = "Block device %s has been mapped to %s through %s as %s%s-%s."; print_error(msg, return_message, device, ((strlen(host) == 0) ? "all hosts" : (char *)host), ((port == INVALID_VALUE) ? "all ports" : (char *)path), NQN_HDR_STR, hostname, device); return SUCCESS; } @@ -759,8 +758,7 @@ int nvmet_revalidate_size(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char rc_prof = rc_prof->next; } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, device); + print_error(ERR_DEV_NOEXIST, return_message, device); return INVALID_VALUE; } else rc = INVALID_VALUE; @@ -769,7 +767,7 @@ int nvmet_revalidate_size(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char sprintf(path, "%s/%s%s-%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); if (access(path, F_OK) != SUCCESS) { sprintf(path, "%s%s-%s", NQN_HDR_STR, hostname, device); - msg = "Error. NQN export: %s does not exist"; + msg = "Error. NQN export: %s does not exist."; print_error(msg, return_message, path); return rc; } @@ -777,7 +775,7 @@ int nvmet_revalidate_size(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char /* Check if namespace 1 exists. That is the only namespace we define. */ sprintf(path, "%s/%s%s-%s/namespaces/1", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); if (access(path, F_OK) != SUCCESS) { - msg = "%s: A RapidDisk defined namespace does not exist"; + msg = "%s: A RapidDisk defined namespace does not exist."; print_error(msg, return_message, __func__); return rc; } @@ -830,7 +828,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa sprintf(path, "%s/%s%s-%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); if (access(path, F_OK) != SUCCESS) { sprintf(path, "%s%s-%s", NQN_HDR_STR, hostname, device); - msg = "Error. NQN export: %s does not exist"; + msg = "Error. NQN export: %s does not exist."; print_error(msg, return_message, path); return rc; } @@ -838,7 +836,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa /* Check if namespace 1 exists. That is the only namespace we define. */ sprintf(path, "%s/%s%s-%s/namespaces/1", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); if (access(path, F_OK) != SUCCESS) { - msg = "%s: A RapidDisk defined namespace does not exist"; + msg = "%s: A RapidDisk defined namespace does not exist."; print_error(msg, return_message, __func__); return rc; } @@ -897,7 +895,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa if (err > 0) { for (n = 0; n < err; n++) { if (strncmp(list[n]->d_name, ".", 1) != SUCCESS) { - msg = "The target is still mapped to host NQN %s"; + msg = "The target is still mapped to host NQN %s."; print_error(msg, return_message, list[n]->d_name); } } @@ -920,7 +918,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa } } else { /* The NVMe Target interface port number that was defined does not exist on the system */ - msg = "%s: Port %d and / or export does not exist"; + msg = "%s: Port %d and / or export does not exist."; print_error(msg, return_message, __func__, port); return rc; } @@ -933,7 +931,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa */ if ((port != INVALID_VALUE) && (hostno == 0)) { if (access(path, F_OK) == SUCCESS) { - msg = "Error. Target is still exported through the port: %s"; + msg = "Error. Target is still exported through the port: %s."; print_error(msg, return_message, __func__, path); return INVALID_VALUE; } @@ -1151,7 +1149,7 @@ int nvmet_disable_port(int port, char *return_message) sprintf(path, "%s/%d", SYS_NVMET_PORTS, port); if (access(path, F_OK) != SUCCESS) { - msg = "Error. NVMe Target Port %d does not exist"; + msg = "Error. NVMe Target Port %d does not exist."; print_error(msg, return_message, port); return rc; } diff --git a/src/rdsk.c b/src/rdsk.c index cdcecd9..54ae474 100644 --- a/src/rdsk.c +++ b/src/rdsk.c @@ -654,8 +654,7 @@ int cache_device_map(struct RD_PROFILE *rd_prof, struct RC_PROFILE *rc_prof, cha rd_prof = rd_prof->next; } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, ramdisk); + print_error(ERR_DEV_NOEXIST, return_message, ramdisk); return -ENOENT; } @@ -803,8 +802,7 @@ int mem_device_resize(struct RD_PROFILE *prof, char *string, unsigned long long prof = prof->next; } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, string); + print_error(ERR_DEV_NOEXIST, return_message, string); return -ENOENT; } @@ -853,7 +851,7 @@ int mem_device_resize(struct RD_PROFILE *prof, char *string, unsigned long long return -EIO; } fclose(fp); - print_error("Resized device %s to %llu Mbytes", return_message, string, size); + print_error("Resized device %s to %llu Mbytes.", return_message, string, size); return SUCCESS; } @@ -901,7 +899,7 @@ int mem_device_attach(struct RD_PROFILE *prof, unsigned long long size, char *re } fclose(fp); - print_error("Attached device rd%d of size %llu Mbytes", return_message, dsk, size); + print_error("Attached device rd%d of size %llu Mbytes.", return_message, dsk, size); return SUCCESS; } @@ -929,8 +927,7 @@ int mem_device_detach(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *str rd_prof = rd_prof->next; } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, string); + print_error(ERR_DEV_NOEXIST, return_message, string); return INVALID_VALUE; } /* Check to make sure RapidDisk device isn't in a mapping */ @@ -983,7 +980,7 @@ int mem_device_detach(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *str } fclose(fp); - print_error("Detached device %s", return_message, string); + print_error("Detached device %s.", return_message, string); if (buf) free(buf); return SUCCESS; @@ -1013,8 +1010,7 @@ int mem_device_lock(struct RD_PROFILE *rd_prof, char *string, bool lock, char *r } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, string); + print_error(ERR_DEV_NOEXIST, return_message, string); return -ENOENT; } @@ -1062,8 +1058,7 @@ int cache_device_unmap(struct RC_PROFILE *prof, char *string, char *return_messa prof = prof->next; } if (rc != SUCCESS) { - msg = "Error. Cache target %s does not exist"; - print_error(msg, return_message, string); + print_error(ERR_CACHE_TGT_NOEXIST, return_message, string); return -ENOENT; } @@ -1093,7 +1088,7 @@ int cache_device_unmap(struct RC_PROFILE *prof, char *string, char *return_messa /* if the mapping is a write-back one, flush before remove */ if (strstr(string, "rc-wb") != NULL) { if ((rc = dm_flush_device(string) != SUCCESS)) { - msg = "Unable to flush dirty cache data to %s"; + msg = "Unable to flush dirty cache data to %s."; print_error(msg, return_message, string); return rc; } @@ -1131,14 +1126,13 @@ int mem_device_flush(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *stri rd_prof = rd_prof->next; } if (rc != SUCCESS) { - msg = "Error. Device %s does not exist"; - print_error(msg, return_message, string); + print_error(ERR_DEV_NOEXIST, return_message, string); return -ENOENT; } /* Check to make sure RapidDisk device isn't in a mapping */ while (rc_prof != NULL) { if (strcmp(string, rc_prof->cache) == SUCCESS) { - msg = "Error. Unable to remove %s. This RapidDisk device is currently mapped as a cache drive to %s"; + msg = "Error. Unable to remove %s. This RapidDisk device is currently mapped as a cache drive to %s."; print_error(msg, return_message, string, rc_prof->device); return -EBUSY; } @@ -1146,7 +1140,7 @@ int mem_device_flush(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *stri } if ((buf = calloc(1, BUFSZ)) == NULL) { - msg = "%s: malloc: Unable to allocate memory"; + msg = "%s: malloc: Unable to allocate memory."; print_error(msg, return_message, __func__); return -ENOMEM; } @@ -1161,7 +1155,7 @@ int mem_device_flush(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *stri fread(buf, BUFSZ, 1, fp); fclose(fp); if ((strstr(buf, string) != NULL)) { - msg = "%s is currently mounted. Please \"umount\" and retry"; + msg = "%s is currently mounted. Please \"umount\" and retry."; print_error(msg, return_message, string); if (buf) free(buf); return -EBUSY; @@ -1182,7 +1176,7 @@ int mem_device_flush(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *stri return -EIO; } close(fd); - print_error("Flushed all data from device %s", return_message, string); + print_error("Flushed all data from device %s.", return_message, string); return SUCCESS; } @@ -1269,8 +1263,7 @@ int cache_wb_device_stat(struct RC_PROFILE *rc_prof, char *cache) rc_prof = rc_prof->next; } if (rc != SUCCESS) { - msg = "Error. Cache target %s does not exist"; - print_error(msg, NULL, cache); + print_error(ERR_CACHE_TGT_NOEXIST, NULL, cache); return -ENOENT; } struct WC_STATS *wc_stats = dm_get_status(cache, WRITEBACK); @@ -1310,8 +1303,7 @@ int cache_device_stat(struct RC_PROFILE *rc_prof, char *cache) rc_prof = rc_prof->next; } if (rc != SUCCESS) { - msg = "Error. Cache target %s does not exist"; - print_error(msg, NULL, cache); + print_error(ERR_CACHE_TGT_NOEXIST, NULL, cache); return -ENOENT; } struct RC_STATS *rc_stats = dm_get_status(cache, WRITETHROUGH); @@ -1354,8 +1346,7 @@ int cache_device_stat_json(struct RC_PROFILE *rc_prof, char *cache, RC_STATS **r rc_prof = rc_prof->next; } if (rc != SUCCESS) { - msg = "Error. Cache target %s does not exist"; - print_error(msg, status_message, cache); + print_error(ERR_CACHE_TGT_NOEXIST, status_message, cache); print_message(rc, status_message, TRUE); return -ENOENT; } @@ -1391,8 +1382,7 @@ int cache_wb_device_stat_json(struct RC_PROFILE *rc_prof, char *cache, WC_STATS rc_prof = rc_prof->next; } if (rc != SUCCESS) { - msg = "Error. Cache target %s does not exist"; - print_error(msg, status_message, cache); + print_error(ERR_CACHE_TGT_NOEXIST, status_message, cache); print_message(rc, status_message, TRUE); return -ENOENT; } From 1f668284f5b9341241268d39d13137475fa65934 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Fri, 30 Dec 2022 21:45:25 +0000 Subject: [PATCH 05/10] Adding notes for NVMe Target support, fixing dates and unexporting target logic. --- README.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ doc/rapiddisk.1 | 43 +++++++++++++++++++++++++++++++ doc/rapiddiskd.1 | 2 +- src/common.h | 2 +- src/json.c | 2 +- src/json.h | 2 +- src/main.c | 5 ++-- src/main.h | 2 +- src/net.c | 2 +- src/nvmet.c | 16 +++++------- src/nvmet.h | 2 +- src/rapiddiskd.c | 12 ++++----- src/rapiddiskd.h | 2 +- src/rdsk.c | 2 +- src/rdsk.h | 2 +- src/sys.c | 2 +- src/sys.h | 6 ++--- src/utils.c | 18 +++++++++++-- src/utils.h | 3 ++- 19 files changed, 156 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index bb9276f..fa5e1e8 100644 --- a/README.md +++ b/README.md @@ -206,3 +206,69 @@ To start the service at boot via systemd: ```console # systemctl enable rapiddiskd.service ``` + +## Managing RapidDisk as an NVMe Target +There are a few things that need to be known when using the NVMe Target +features of the RapidDisk suite. + +### Loading the NVMe Target Kernel Modules +In order to map any RapidDisk device and export it in the NVMe Target +framework, the nvmet and the nvmet-tcp or nvmet-rdma kernel modules must be +inserted. + +```console +# modprobe nvmet nvmet-tcp +``` + +### Enabling NVMe Target Ports +At least one Ethernet interface will need to be configured as a target +port to export the RapidDisk volume from. + +```console +# rapiddisk -i eth -P 1 -t tcp +``` + +### Exporting Targets +When exporting a volume, a RapidDisk volume and a target port must be +defined. If a host NQN is not defined, the administration utility will +provide access to any host NQN. Note - a target can be exported across more +than one target port. + +```console +# rapiddisk -e -b rd3 -P 1 +``` + +If a host NQN is defined, access is restricted to only those host NQNs. +Note - the following command example can be repeated multiple times to add +additional host NQNs for the specified target export. + +```console +# rapiddisk -e -b rd3 -P 1 -H nqn.host1 +``` + +### Unexporting Targets +Unexporting RapidDisk volumes looks a bit different than exporting. If a +host NQN is defined for a specified target, only that NQN will be removed from +accessing the exported target. + +```console +# rapiddisk -x -b rd3 -H nqn.host1 +``` + +Removing all allowed host NQNs will revert access to any and all host NQNs +requesting access to the target. + +If a target port is defined, the exported target will not be exported from the +interface if one condition is met: the target has no defined allowed host NQNs. + +```console +# rapiddisk -x -b rd3 -P 1 -H nqn.host1 +``` +OR + +```console +# rapiddisk -x -b rd3 -P 1 +``` + +And if there are no defined allowed host NQNs and the target is not being exported +across any target ports, the entire target is removed from the subsystem. diff --git a/doc/rapiddisk.1 b/doc/rapiddisk.1 index b6781af..ce71ec5 100755 --- a/doc/rapiddisk.1 +++ b/doc/rapiddisk.1 @@ -32,6 +32,9 @@ Export a RapidDisk block device as an NVMe Target. -f Erase all data to a specified RapidDisk device (dangerous). .TP +-g +Do not print header. +.TP -H The host to export / unexport the NVMe Target to / from. .TP @@ -133,6 +136,46 @@ rapiddisk -e -b rd3 -P 1 -H nqn.host1 rapiddisk -R -b rd0 .TP rapiddisk -x -b rd3 -P 1 -H nqn.host1 +.SH MANAGING RAPIDDISK AS AN NVME TARGET +There are a few things that need to be known when using the NVMe Target features of the RapidDisk suite. +.TP +1. +In order to map any RapidDisk device and export it in the NVMe Target framework, the nvmet and the nvmet-tcp or nvmet-rdma kernel modules must be inserted. +.TP +2. +At least one Ethernet interface will need to be configured as a target port to export the RapidDisk volume from. +.RS +.P +ex) rapiddisk -i eth -P 1 -t tcp +.RE +.TP +3. +When exporting a volume, a RapidDisk volume and a target port must be defined. If a host NQN is not defined, the administration utility will provide access to any host NQN. Note - a target can be exported across more than one target port. +.RS +.P +ex) rapiddisk -e -b rd3 -P 1 +.P +If a host NQN is defined, access is restricted to only those host NQNs. Note - the following command example can be repeated multiple times to add additional host NQNs for the specified target export. +.P +ex) rapiddisk -e -b rd3 -P 1 -H nqn.host1 +.RE +.TP +4. +Unexporting RapidDisk volumes looks a bit different than exporting. If a host NQN is defined for a specified target, only that NQN will be removed from accessing the exported target. +.RS +.P +ex) rapiddisk -x -b rd3 -H nqn.host1 +.P +Removing all allowed host NQNs will revert access to any and all host NQNs requesting access to the target. +.P +If a target port is defined, the exported target will not be exported from the interface if one condition is met: the target has no defined allowed host NQNs. +.P +ex) rapiddisk -x -b rd3 -P 1 -H nqn.host1 +.P +ex) rapiddisk -x -b rd3 -P 1 +.P +And if there are no defined allowed host NQNs and the target is not being exported across any target ports, the entire target is removed from the subsystem. +.RE .SH EXIT STATUS rapiddisk returns a zero exit status if no error occurs during operation. A non-zero value is returned on error. .SH AUTHORS diff --git a/doc/rapiddiskd.1 b/doc/rapiddiskd.1 index b0024b8..72e9c5f 100755 --- a/doc/rapiddiskd.1 +++ b/doc/rapiddiskd.1 @@ -17,7 +17,7 @@ Invoke the help menu. Change port to listen on (default: 9118). .TP -V -Enable debug messages to stdout (this is ugly). +Enable debug messages to stderr (this is ugly). .TP -v Display the version number. diff --git a/src/common.h b/src/common.h index 7107fbd..fb9d7db 100644 --- a/src/common.h +++ b/src/common.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef COMMON_H #define COMMON_H diff --git a/src/json.c b/src/json.c index afe9aff..6dbe7bb 100644 --- a/src/json.c +++ b/src/json.c @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #include "common.h" diff --git a/src/json.h b/src/json.h index 8ceca04..dedf4ce 100644 --- a/src/json.h +++ b/src/json.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef JSON_H diff --git a/src/main.c b/src/main.c index bbaa3dd..bbac52d 100644 --- a/src/main.c +++ b/src/main.c @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #include "main.h" @@ -54,7 +54,7 @@ void online_menu(char *string) "\t-d\t\tDetach RAM disk device.\n" "\t-e\t\tExport a RapidDisk block device as an NVMe Target.\n" "\t-f\t\tErase all data to a specified RapidDisk device \033[31;1m(dangerous)\033[0m.\n" - "\t-g\t\tDo not print header, useful with -j.\n" + "\t-g\t\tDo not print header.\n" "\t-H\t\tThe host to export / unexport the NVMe Target to / from.\n" "\t-h\t\tDisplay the help menu.\n" "\t-i\t\tDefine the network interface to enable for NVMe Target exporting.\n" @@ -149,6 +149,7 @@ int exec_cmdline_arg(int argcin, char *argvin[]) sprintf(host, "%s", optarg); break; case 'j': + header_flag = FALSE; json_flag = TRUE; break; case 'L': diff --git a/src/main.h b/src/main.h index eac0f8b..684791e 100644 --- a/src/main.h +++ b/src/main.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef MAIN_H diff --git a/src/net.c b/src/net.c index 7a1b5ba..3f79e46 100644 --- a/src/net.c +++ b/src/net.c @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #define SERVER diff --git a/src/nvmet.c b/src/nvmet.c index f91e3ab..d4c4334 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #include "nvmet.h" @@ -886,19 +886,15 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa * proceed with the rest */ sprintf(path, "%s/%s%s-%s/allowed_hosts/", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((err = scandir(path, &list, NULL, NULL)) < 0) { + if ((err = scandir(path, &list, scandir_filter_no_dot, NULL)) < 0) { msg = "Error. Unable to scan host exports directory for %s. %s: unlink: %s"; print_error(msg, return_message, path, __func__, strerror(errno)); return rc; } - hostno = err; - if (err > 0) { - for (n = 0; n < err; n++) { - if (strncmp(list[n]->d_name, ".", 1) != SUCCESS) { - msg = "The target is still mapped to host NQN %s."; - print_error(msg, return_message, list[n]->d_name); - } - } + for (n = 0; n < err; n++) { + hostno++; + msg = "The target is still mapped to host NQN %s."; + print_error(msg, return_message, list[n]->d_name); } list = clean_scandir(list, err); diff --git a/src/nvmet.h b/src/nvmet.h index 1a84ef1..f43d6fe 100644 --- a/src/nvmet.h +++ b/src/nvmet.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef NVMET_H diff --git a/src/rapiddiskd.c b/src/rapiddiskd.c index 57ece46..45af28e 100644 --- a/src/rapiddiskd.c +++ b/src/rapiddiskd.c @@ -24,7 +24,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #define SERVER @@ -107,9 +107,13 @@ int main(int argc, char *argv[]) } #endif - while ((i = getopt(argc, argv, "?hp:vVd")) != INVALID_VALUE) { + while ((i = getopt(argc, argv, "?dhp:vV")) != INVALID_VALUE) { switch (i) { case '?': + case 'd': + verbose = 1; + debug = 1; + break; case 'h': online_menu(); return SUCCESS; @@ -153,10 +157,6 @@ int main(int argc, char *argv[]) case 'V': verbose = 1; break; - case 'd': - verbose = 1; - debug = 1; - break; default: break; } diff --git a/src/rapiddiskd.h b/src/rapiddiskd.h index 584a04f..c5e4f31 100644 --- a/src/rapiddiskd.h +++ b/src/rapiddiskd.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef DAEMON_H diff --git a/src/rdsk.c b/src/rdsk.c index 54ae474..53d8ed3 100644 --- a/src/rdsk.c +++ b/src/rdsk.c @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #include "rdsk.h" diff --git a/src/rdsk.h b/src/rdsk.h index eb3e781..ac9694e 100644 --- a/src/rdsk.h +++ b/src/rdsk.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef RDSK_H diff --git a/src/sys.c b/src/sys.c index 3373742..d5a79a4 100644 --- a/src/sys.c +++ b/src/sys.c @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #include "sys.h" diff --git a/src/sys.h b/src/sys.h index a63a3dd..5a057ae 100644 --- a/src/sys.h +++ b/src/sys.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef SYS_H #define SYS_H @@ -37,7 +37,7 @@ SPDX-License-Identifier: GPL-2.0-or-later #ifndef SERVER int resources_list(struct MEM_PROFILE *, struct VOLUME_PROFILE *); #endif -int get_memory_usage(struct MEM_PROFILE *, char *return_message); -struct VOLUME_PROFILE *search_volumes_targets(char *return_message); +int get_memory_usage(struct MEM_PROFILE *, char *); +struct VOLUME_PROFILE *search_volumes_targets(char *); #endif //SYS_H diff --git a/src/utils.c b/src/utils.c index 7fab7c8..0d59db7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,5 +1,5 @@ /** - * @file util.c + * @file utils.c * @brief Utility function definitions * @details This file contains all the utility functions * @copyright @verbatim @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 -* @date 26 September 2022 +* @date 30 December 2023 */ #include "utils.h" #include "json.h" @@ -372,3 +372,17 @@ void print_message(int ret_value, char *message, bool json_flag) { printf("%s\n", message); } } + +/** + * If the file name starts with a dot, return false. Otherwise, return true. + * + * @param list This is the directory entry that is being passed to the function. + * + * @return the number of files in the directory. + */ +int scandir_filter_no_dot(const struct dirent *list) { + if (strncmp(list->d_name, ".", 1) == SUCCESS) { + return FALSE; + } + return TRUE; +} diff --git a/src/utils.h b/src/utils.h index 8049267..fca8656 100644 --- a/src/utils.h +++ b/src/utils.h @@ -27,7 +27,7 @@ SPDX-License-Identifier: GPL-2.0-or-later * @author Petros Koutoupis \ * @author Matteo Tenca \ * @version 9.0.0 - * @date 26 September 2022 + * @date 30 December 2023 */ #ifndef UTILS_H #define UTILS_H @@ -36,6 +36,7 @@ SPDX-License-Identifier: GPL-2.0-or-later int preg_replace(const char *re, char *replacement, char *subject, char *result, size_t pcre2_result_len); int split(char* input_string, char** output_arr, char* delim); +int scandir_filter_no_dot(const struct dirent *); void free_linked_lists(RC_PROFILE *rc_head, RD_PROFILE *rd_head, VOLUME_PROFILE *vp_head); void free_nvmet_linked_lists(struct NVMET_PORTS *ports_head, struct NVMET_PROFILE *nvmet_head); struct dirent **clean_scandir(struct dirent **scanlist, int num); From e47866707442a914bc3ae7ce85b7168609992498 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Sat, 7 Jan 2023 07:24:41 +0000 Subject: [PATCH 06/10] Cleanup comments and fix bug in exporting NVMe devices to hosts. --- README.md | 6 +++--- src/Makefile | 7 ++++--- src/nvmet.c | 21 ++++++++++----------- src/rdsk.c | 3 +-- src/sys.h | 6 +++--- src/utils.h | 2 +- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index fa5e1e8..d53a6da 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ An example of a POST command: Change into the project's parent directory path. > To build the rapiddisk management utility, you will need to have the -> `libjansson`, `libpcre2-dev`, `libdevmapper` and `libmicrohttpd` +> `libjansson`, `libpcre2`, `libdevmapper` and `libmicrohttpd` > development library files installed on your host system. > > You are required to having either the full kernel source or the kernel @@ -210,7 +210,7 @@ To start the service at boot via systemd: ## Managing RapidDisk as an NVMe Target There are a few things that need to be known when using the NVMe Target features of the RapidDisk suite. - + ### Loading the NVMe Target Kernel Modules In order to map any RapidDisk device and export it in the NVMe Target framework, the nvmet and the nvmet-tcp or nvmet-rdma kernel modules must be @@ -240,7 +240,7 @@ than one target port. If a host NQN is defined, access is restricted to only those host NQNs. Note - the following command example can be repeated multiple times to add -additional host NQNs for the specified target export. +additional host NQNs for the specified target export. ```console # rapiddisk -e -b rd3 -P 1 -H nqn.host1 diff --git a/src/Makefile b/src/Makefile index e68fb0e..30996dd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -64,6 +64,7 @@ SRC := json.c main.c net.c nvmet.c rapiddiskd.c rdsk.c sys.c utils.c .PHONY: all all: $(BIN_TOOL_NDEBUG) $(BIN_DAEMON_NDEBUG) + @echo Successfully built all $(BIN_TOOL_NDEBUG) and $(BIN_DAEMON_NDEBUG) binary files. # This checks avoid creating/including the .h dependencies Makefiles # Disables parallelization if "clean" is present in the goal list @@ -108,7 +109,7 @@ tools-strip: all .PHONY: install install: all - @echo Installing all $(BIN_TOOL_NDEBUG) $(BIN_DAEMON_NDEBUG) binary files. + @echo Installing all $(BIN_TOOL_NDEBUG) and $(BIN_DAEMON_NDEBUG) binary files. $(INSTALL) $(BIN_TOOL_NDEBUG) $(BIN_DAEMON_NDEBUG) .PHONY: install-strip @@ -116,12 +117,12 @@ install-strip: tools-install-strip .PHONY: tools-install-strip tools-install-strip: all - @echo Installing stripped $(BIN_TOOL_NDEBUG) $(BIN_DAEMON_NDEBUG) binary files. + @echo Installing stripped $(BIN_TOOL_NDEBUG) and $(BIN_DAEMON_NDEBUG) binary files. $(INSTALL_STRIP) $(BIN_TOOL_NDEBUG) $(BIN_DAEMON_NDEBUG) .PHONY: uninstall uninstall: - @echo Uninstalling $(BIN_TOOL_NDEBUG) $(BIN_DAEMON_NDEBUG) binary files. + @echo Uninstalling $(BIN_TOOL_NDEBUG) and $(BIN_DAEMON_NDEBUG) binary files. $(RM) $(DESTDIR)$(DIR)/$(BIN_TOOL_NDEBUG) $(RM) $(DESTDIR)$(DIR)/$(BIN_DAEMON_NDEBUG) diff --git a/src/nvmet.c b/src/nvmet.c index d4c4334..c62ae68 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -538,7 +538,6 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d char hostname[0x40] = {0x0}, path[NAMELEN] = {0x0}, path2[NAMELEN] = {0x0}; struct dirent **list; char *msg; - char error_message[NAMELEN] = {0}; /* * We do not care if the device has already been exported. We will continue to go through @@ -606,6 +605,16 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d } else { /* Configure the target to be seen only by the specified host(s) */ + /* Make sure that no other hosts can access the target */ + sprintf(path, "%s/%s%s-%s/attr_allow_any_host", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); + if ((fp = fopen(path, "w")) == NULL){ + msg = "Error. Unable to open %s. %s: fopen: %s"; + print_error(msg, return_message, path, __func__, strerror(errno)); + return INVALID_VALUE; + } + fprintf(fp, "0"); + fclose(fp); + sprintf(path, "%s/%s", SYS_NVMET_HOSTS, host); if (access(path, F_OK) != SUCCESS) { if ((rc = mkdir(path, mode)) != SUCCESS) { @@ -625,16 +634,6 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d return rc; } } - - /* Make sure that no other hosts can access the target */ - sprintf(path, "%s/%s%s-%s/attr_allow_any_host", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((fp = fopen(path, "w")) == NULL){ - msg = "Error. Unable to open %s. %s: fopen: %s"; - print_error(msg, return_message, path, __func__, strerror(errno)); - return INVALID_VALUE; - } - fprintf(fp, "0"); - fclose(fp); } /* Set model */ diff --git a/src/rdsk.c b/src/rdsk.c index 53d8ed3..bdc4617 100644 --- a/src/rdsk.c +++ b/src/rdsk.c @@ -511,8 +511,7 @@ void *dm_get_status(char* device, enum CACHE_TYPE cache_type) { return NULL; } - dm_get_next_target(dmt, NULL, &start, &length, - &target_type, ¶ms); + dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms); if (target_type) { size_t result_size = strlen(params) * 2; char *result = calloc(1, result_size); diff --git a/src/sys.h b/src/sys.h index 5a057ae..a693947 100644 --- a/src/sys.h +++ b/src/sys.h @@ -35,9 +35,9 @@ SPDX-License-Identifier: GPL-2.0-or-later #include "common.h" #ifndef SERVER -int resources_list(struct MEM_PROFILE *, struct VOLUME_PROFILE *); +int resources_list(struct MEM_PROFILE *mem_profile, struct VOLUME_PROFILE *); #endif -int get_memory_usage(struct MEM_PROFILE *, char *); -struct VOLUME_PROFILE *search_volumes_targets(char *); +int get_memory_usage(struct MEM_PROFILE *mem_profile, char *return_message); +struct VOLUME_PROFILE *search_volumes_targets(char *return_message); #endif //SYS_H diff --git a/src/utils.h b/src/utils.h index fca8656..b2a1121 100644 --- a/src/utils.h +++ b/src/utils.h @@ -36,7 +36,7 @@ SPDX-License-Identifier: GPL-2.0-or-later int preg_replace(const char *re, char *replacement, char *subject, char *result, size_t pcre2_result_len); int split(char* input_string, char** output_arr, char* delim); -int scandir_filter_no_dot(const struct dirent *); +int scandir_filter_no_dot(const struct dirent *list); void free_linked_lists(RC_PROFILE *rc_head, RD_PROFILE *rd_head, VOLUME_PROFILE *vp_head); void free_nvmet_linked_lists(struct NVMET_PORTS *ports_head, struct NVMET_PROFILE *nvmet_head); struct dirent **clean_scandir(struct dirent **scanlist, int num); From 1441b31759e2cbeb543b986b631983f0d317d156 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Sat, 7 Jan 2023 08:11:40 +0000 Subject: [PATCH 07/10] Fixed messaging in unexport function (for json support). --- src/nvmet.c | 92 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/src/nvmet.c b/src/nvmet.c index c62ae68..2ca66b2 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -817,11 +817,13 @@ int nvmet_revalidate_size(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char */ int nvmet_unexport_volume(char *device, char *host, int port, char *return_message) { - int rc = INVALID_VALUE, n, err, hostno = 0; + int rc = INVALID_VALUE, n, err, hostno = 0, allowed_host_number = 0; FILE *fp; char hostname[0x40] = {0x0}, path[NAMELEN] = {0x0}; struct dirent **list; char *msg; + char json_message[NAMELEN] = {0}; + char json_message_temp[NAMELEN] = {0}; gethostname(hostname, sizeof(hostname)); sprintf(path, "%s/%s%s-%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); @@ -842,7 +844,7 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa /* Make sure that no other namespaces exist. We do not create anything higher than 1. */ sprintf(path, "%s/%s%s-%s/namespaces/", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((err = scandir(path, &list, NULL, NULL)) < 0) { + if ((err = scandir(path, &list, scandir_filter_no_dot, NULL)) < 0) { msg = "Error. Unable to access %s. %s: scandir: %s"; print_error(msg, return_message, path, __func__, strerror(errno)); return INVALID_VALUE; @@ -850,12 +852,23 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa list = clean_scandir(list, err); - if (err > 3) { + if (err > 1) { msg = "An invalid number of namespaces not created by RapidDisk exist."; print_error("%s", return_message, msg); return rc; } + /* + * Grab number of entries in allowed_hosts directory. We need this later, to check if one of them has been removed. + */ + sprintf(path, "%s/%s%s-%s/allowed_hosts/", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); + if ((allowed_host_number = scandir(path, &list, scandir_filter_no_dot, NULL)) < 0) { + msg = "Error. Unable to scan host exports directory for %s. %s: unlink: %s"; + print_error(msg, return_message, path, __func__, strerror(errno)); + return rc; + } + list = clean_scandir(list, allowed_host_number); + /* Remove host NQN */ if (strlen(host) != 0) { sprintf(path, "%s/%s%s-%s/allowed_hosts/%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device, host); @@ -866,14 +879,17 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa print_error(msg, return_message, __func__, strerror(errno)); return rc; } + msg = "Block device %s has been unmapped from NVMe Initiator host %s."; if (return_message == NULL) { - msg = "Block device %s has been unmapped from NVMe Target host %s."; print_error(msg, return_message, device, host); + } else { + sprintf(json_message_temp, msg, device, host); + strcat(json_message, json_message_temp); } } else { - msg = "%s: Host %s does not exist"; - print_error(msg, return_message, __func__, host); - return rc; + msg = "NVMe Initiator Host '%s' does not exist."; + print_error(msg, return_message, host); + return INVALID_VALUE; } /* If a host is defined without any port number, just remove and exit. */ if (port == INVALID_VALUE) @@ -882,20 +898,32 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa /* * Grab number of entries in allowed_hosts directory. If more than zero still exist, we will not - * proceed with the rest + * proceed with the rest. If an entry was removed, the operation is considered successful. */ sprintf(path, "%s/%s%s-%s/allowed_hosts/", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((err = scandir(path, &list, scandir_filter_no_dot, NULL)) < 0) { + if ((hostno = scandir(path, &list, scandir_filter_no_dot, NULL)) < 0) { msg = "Error. Unable to scan host exports directory for %s. %s: unlink: %s"; print_error(msg, return_message, path, __func__, strerror(errno)); return rc; } - for (n = 0; n < err; n++) { - hostno++; - msg = "The target is still mapped to host NQN %s."; - print_error(msg, return_message, list[n]->d_name); + + if (hostno > 0) { + if (strlen(json_message) > 0) { + strcat(json_message, " "); + } + strcat(json_message, "One or more target(s) is/are still mapped to NQN(s): "); + for (n = 0; n < hostno; n++) { + strcat(json_message, list[n]->d_name); + strcat(json_message, ", "); + } + + size_t size = strlen(json_message); + size = size - 2; + json_message[size] = '\0'; + strcat(json_message, "."); } - list = clean_scandir(list, err); + + list = clean_scandir(list, hostno); /* Remove NVMe Target interface port */ if ((port != INVALID_VALUE) && (hostno == 0)) { @@ -907,9 +935,15 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa print_error(msg, return_message, __func__, strerror(errno)); return rc; } + msg = "Block device %s has been unmapped from NVMe Target port %d."; if (return_message == NULL) { - msg = "Block device %s has been unmapped from NVMe Target port %d."; print_error(msg, return_message, device, port); + } else { + sprintf(json_message_temp, msg, device, port); + if (strlen(json_message) > 0) { + strcat(json_message, " "); + } + strcat(json_message, json_message_temp); } } else { /* The NVMe Target interface port number that was defined does not exist on the system */ @@ -959,11 +993,33 @@ int nvmet_unexport_volume(char *device, char *host, int port, char *return_messa return rc; } } - msg = "Block device %s has been removed from the NVMe Target subsystem."; - print_error(msg, return_message, device); } - return SUCCESS; + if ((strlen(json_message) == 0) || hostno == 0) { + rc = SUCCESS; + msg = "Block device %s has been removed from the NVMe Target subsystem."; + sprintf(json_message_temp, msg, device); + if (strlen(json_message) > 0) { + strcat(json_message, " "); + } + strcat(json_message, json_message_temp); + print_error("%s", return_message, json_message); + } else if ((allowed_host_number - hostno) > 0) { + rc = SUCCESS; + msg = "Block device %s could not be removed from the NVMe Target subsystem, but has been unmapped from NVMe Target host %s."; + sprintf(json_message_temp, msg, device, host); + if (strlen(json_message) > 0) { + strcat(json_message, " "); + } + strcat(json_message, json_message_temp); + printf("-%s-\n", json_message); + print_error("%s", return_message, json_message); + } else { + rc = INVALID_VALUE; + msg = "Block device %s could not be removed from the NVMe Target subsystem for unspecified host. %s"; + print_error(msg, return_message, device, json_message); + } + return rc; } /* From 9aa7e4a875b7e9854867b4a1886dcdefc1d83331 Mon Sep 17 00:00:00 2001 From: Matteo Tenca <93343338+matteotenca@users.noreply.github.com> Date: Wed, 11 Jan 2023 20:31:46 +0100 Subject: [PATCH 08/10] Fix missing check for port when exporting/unexporting (NVMe) Add a new #define for an error message in common.h. Use scandir_filter_no_dot() filter for scandir() more often. --- src/common.h | 1 + src/nvmet.c | 236 +++++++++++++++++++++++++++------------------------ 2 files changed, 127 insertions(+), 110 deletions(-) diff --git a/src/common.h b/src/common.h index fb9d7db..ffee82c 100644 --- a/src/common.h +++ b/src/common.h @@ -90,6 +90,7 @@ typedef char bool; #define ERR_SIGPIPE_HANDLER "Failed to install SIGPIPE handler: %s, %s" #define ERR_INVALID_MODE "Invalid cache mode in URL." #define ERR_DEV_NOEXIST "Error. Device %s does not exist." +#define ERR_PORT_NOEXIST "Error. Port %d does not exist." #define ERR_CACHE_TGT_NOEXIST "Error. Cache target %s does not exist." /** diff --git a/src/nvmet.c b/src/nvmet.c index 2ca66b2..92c668c 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -177,71 +177,67 @@ struct NVMET_PORTS *nvmet_scan_ports(char *return_message) return NULL; } - if ((err = scandir(SYS_NVMET_PORTS, &ports, NULL, NULL)) < 0) { + if ((err = scandir(SYS_NVMET_PORTS, &ports, scandir_filter_no_dot, NULL)) < 0) { msg = "%s: scandir: %s"; print_error(msg, return_message, __func__, strerror(errno)); return NULL; } for (; n < err; n++) { - if (strncmp(ports[n]->d_name, ".", 1) != SUCCESS) { - memset(file, 0x0, NAMELEN); - sprintf(file, "%s/%s", SYS_NVMET_PORTS, ports[n]->d_name); - if (access(file, F_OK) != INVALID_VALUE) { - sprintf(file, "%s/%s/subsystems", SYS_NVMET_PORTS, ports[n]->d_name); - if ((err2 = scandir(file, &exports, NULL, NULL)) < 0) { - msg = "%s: scandir: %s"; + memset(file, 0x0, NAMELEN); + sprintf(file, "%s/%s", SYS_NVMET_PORTS, ports[n]->d_name); + if (access(file, F_OK) != INVALID_VALUE) { + sprintf(file, "%s/%s/subsystems", SYS_NVMET_PORTS, ports[n]->d_name); + if ((err2 = scandir(file, &exports, scandir_filter_no_dot, NULL)) < 0) { + msg = "%s: scandir: %s"; + print_error(msg, return_message, __func__, strerror(errno)); + ports = clean_scandir(ports, err); + return NULL; + } + for (i = 0; i < err2; i++) { + if ((nvmet_ports = (struct NVMET_PORTS *)calloc(1, sizeof(struct NVMET_PORTS))) == NULL ) { + msg = ERR_CALLOC; print_error(msg, return_message, __func__, strerror(errno)); ports = clean_scandir(ports, err); + exports = clean_scandir(exports, err2); return NULL; } - for (i = 0; i < err2; i++) { - if (strncmp(exports[i]->d_name, ".", 1) != SUCCESS) { - if ((nvmet_ports = (struct NVMET_PORTS *)calloc(1, sizeof(struct NVMET_PORTS))) == NULL ) { - msg = ERR_CALLOC; - print_error(msg, return_message, __func__, strerror(errno)); - ports = clean_scandir(ports, err); - exports = clean_scandir(exports, err2); - return NULL; - } - nvmet_ports->port = atoi(ports[n]->d_name); - sprintf(file, "%s/%s", SYS_NVMET_PORTS, ports[n]->d_name); - char *info = read_info(file, "addr_traddr", return_message); - if (info == NULL) { - free(nvmet_ports); - nvmet_ports = NULL; - ports = clean_scandir(ports, err); - exports = clean_scandir(exports, err2); - free_nvmet_linked_lists(ports_head, NULL); - return NULL; - } - sprintf(nvmet_ports->addr, "%s", info); - if (strlen(nvmet_ports->addr) < 1) - sprintf(nvmet_ports->addr, "UNDEFINED"); - info = read_info(file, "addr_trtype", return_message); - if (info == NULL) { - free(nvmet_ports); - nvmet_ports = NULL; - ports = clean_scandir(ports, err); - exports = clean_scandir(exports, err2); - free_nvmet_linked_lists(ports_head, NULL); - return NULL; - } - sprintf(nvmet_ports->protocol, "%s", info); - if (strlen(nvmet_ports->protocol) < 1) - sprintf(nvmet_ports->protocol, "UNDEFINED"); - sprintf(nvmet_ports->nqn, "%s", exports[i]->d_name); - if (strlen(nvmet_ports->nqn) < 1) - sprintf(nvmet_ports->nqn, "UNDEFINED"); - if (ports_head == NULL) - ports_head = nvmet_ports; - else - ports_end->next = nvmet_ports; - ports_end = nvmet_ports; - nvmet_ports->next = NULL; - } + nvmet_ports->port = atoi(ports[n]->d_name); + sprintf(file, "%s/%s", SYS_NVMET_PORTS, ports[n]->d_name); + char *info = read_info(file, "addr_traddr", return_message); + if (info == NULL) { + free(nvmet_ports); + nvmet_ports = NULL; + ports = clean_scandir(ports, err); + exports = clean_scandir(exports, err2); + free_nvmet_linked_lists(ports_head, NULL); + return NULL; } - exports = clean_scandir(exports, err2); + sprintf(nvmet_ports->addr, "%s", info); + if (strlen(nvmet_ports->addr) < 1) + sprintf(nvmet_ports->addr, "UNDEFINED"); + info = read_info(file, "addr_trtype", return_message); + if (info == NULL) { + free(nvmet_ports); + nvmet_ports = NULL; + ports = clean_scandir(ports, err); + exports = clean_scandir(exports, err2); + free_nvmet_linked_lists(ports_head, NULL); + return NULL; + } + sprintf(nvmet_ports->protocol, "%s", info); + if (strlen(nvmet_ports->protocol) < 1) + sprintf(nvmet_ports->protocol, "UNDEFINED"); + sprintf(nvmet_ports->nqn, "%s", exports[i]->d_name); + if (strlen(nvmet_ports->nqn) < 1) + sprintf(nvmet_ports->nqn, "UNDEFINED"); + if (ports_head == NULL) + ports_head = nvmet_ports; + else + ports_end->next = nvmet_ports; + ports_end = nvmet_ports; + nvmet_ports->next = NULL; } + exports = clean_scandir(exports, err2); } } ports = clean_scandir(ports, err); @@ -276,54 +272,52 @@ struct NVMET_PORTS *nvmet_scan_all_ports(char *return_message) return NULL; } - if ((err = scandir(SYS_NVMET_PORTS, &ports, NULL, NULL)) < 0) { + if ((err = scandir(SYS_NVMET_PORTS, &ports, scandir_filter_no_dot, NULL)) < 0) { msg = "%s: scandir: %s"; print_error(msg, return_message, __func__, strerror(errno)); return NULL; } for (; n < err; n++) { - if (strncmp(ports[n]->d_name, ".", 1) != SUCCESS) { - memset(file, 0x0, NAMELEN); - sprintf(file, "%s/%s", SYS_NVMET_PORTS, ports[n]->d_name); - if (access(file, F_OK) != INVALID_VALUE) { - if ((nvmet_ports = (struct NVMET_PORTS *)calloc(1, sizeof(struct NVMET_PORTS))) == NULL ) { - msg = ERR_CALLOC; - print_error(msg, return_message, __func__, strerror(errno)); - ports = clean_scandir(ports, err); - return NULL; - } - nvmet_ports->port = atoi(ports[n]->d_name); - char *info = read_info(file, "addr_traddr", return_message); - if (info == NULL) { - free(nvmet_ports); - nvmet_ports = NULL; - ports = clean_scandir(ports, err); - free_nvmet_linked_lists(ports_head, NULL); - ports_head = NULL; - return NULL; - } - sprintf(nvmet_ports->addr, "%s", info); - if (strlen(nvmet_ports->addr) < 1) - sprintf(nvmet_ports->addr, "UNDEFINED"); - info = read_info(file, "addr_trtype", return_message); - if (info == NULL) { - free(nvmet_ports); - nvmet_ports = NULL; - ports = clean_scandir(ports, err); - free_nvmet_linked_lists(ports_head, NULL); - ports_head = NULL; - return NULL; - } - sprintf(nvmet_ports->protocol, "%s", info); - if (strlen(nvmet_ports->protocol) < 1) - sprintf(nvmet_ports->protocol, "UNDEFINED"); - if (ports_head == NULL) - ports_head = nvmet_ports; - else - ports_end->next = nvmet_ports; - ports_end = nvmet_ports; - nvmet_ports->next = NULL; + memset(file, 0x0, NAMELEN); + sprintf(file, "%s/%s", SYS_NVMET_PORTS, ports[n]->d_name); + if (access(file, F_OK) != INVALID_VALUE) { + if ((nvmet_ports = (struct NVMET_PORTS *)calloc(1, sizeof(struct NVMET_PORTS))) == NULL ) { + msg = ERR_CALLOC; + print_error(msg, return_message, __func__, strerror(errno)); + ports = clean_scandir(ports, err); + return NULL; } + nvmet_ports->port = atoi(ports[n]->d_name); + char *info = read_info(file, "addr_traddr", return_message); + if (info == NULL) { + free(nvmet_ports); + nvmet_ports = NULL; + ports = clean_scandir(ports, err); + free_nvmet_linked_lists(ports_head, NULL); + ports_head = NULL; + return NULL; + } + sprintf(nvmet_ports->addr, "%s", info); + if (strlen(nvmet_ports->addr) < 1) + sprintf(nvmet_ports->addr, "UNDEFINED"); + info = read_info(file, "addr_trtype", return_message); + if (info == NULL) { + free(nvmet_ports); + nvmet_ports = NULL; + ports = clean_scandir(ports, err); + free_nvmet_linked_lists(ports_head, NULL); + ports_head = NULL; + return NULL; + } + sprintf(nvmet_ports->protocol, "%s", info); + if (strlen(nvmet_ports->protocol) < 1) + sprintf(nvmet_ports->protocol, "UNDEFINED"); + if (ports_head == NULL) + ports_head = nvmet_ports; + else + ports_end->next = nvmet_ports; + ports_end = nvmet_ports; + nvmet_ports->next = NULL; } } ports = clean_scandir(ports, err); @@ -538,6 +532,7 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d char hostname[0x40] = {0x0}, path[NAMELEN] = {0x0}, path2[NAMELEN] = {0x0}; struct dirent **list; char *msg; + struct NVMET_PORTS *ports; /* * We do not care if the device has already been exported. We will continue to go through @@ -566,6 +561,29 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d return INVALID_VALUE; } + rc = INVALID_VALUE; + + if (port != INVALID_VALUE) { + ports = nvmet_scan_ports(return_message); + if ((ports == NULL) && (strlen(return_message) != 0)) { + msg = "%s"; + print_error(msg, return_message, return_message); + return INVALID_VALUE; + } + while (ports != NULL) { + if (port == ports->port) { + rc = SUCCESS; + break; + } + ports = ports->next; + } + if (rc != SUCCESS) { + print_error(ERR_PORT_NOEXIST, return_message, port); + free_nvmet_linked_lists(ports, NULL); + return INVALID_VALUE; + } + free_nvmet_linked_lists(ports, NULL); + } /* Create NQN */ gethostname(hostname, sizeof(hostname)); sprintf(path, "%s/%s%s-%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); @@ -580,7 +598,7 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d /* Set host NQNs to access target */ if (strlen(host) == 0) { sprintf(path, "%s/%s%s-%s/allowed_hosts", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - if ((err = scandir(path, &list, NULL, NULL)) < 0) { + if ((err = scandir(path, &list, scandir_filter_no_dot, NULL)) < 0) { msg = "Error. Unable to access %s. %s: scandir: %s"; print_error(msg, return_message, path, __func__, strerror(errno)); return INVALID_VALUE; @@ -588,7 +606,7 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d list = clean_scandir(list, err); - if (err > 2) { + if (err > 0) { msg = "One or more hosts exist. Please remove existing host or define a new one."; print_error("%s", return_message, msg); return INVALID_VALUE; @@ -695,23 +713,21 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d } } else { /* Iterate through all ports and enable target on each */ - if ((err = scandir(SYS_NVMET_PORTS, &list, NULL, NULL)) < 0) { + if ((err = scandir(SYS_NVMET_PORTS, &list, scandir_filter_no_dot, NULL)) < 0) { msg = "%s: scandir: %s"; print_error(msg, return_message, __func__, strerror(errno)); return INVALID_VALUE; } for (n = 0; n < err; n++) { - if (strncmp(list[n]->d_name, ".", 1) != SUCCESS) { - sprintf(path, "%s/%s%s-%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); - sprintf(path2, "%s/%s/subsystems/%s%s-%s", SYS_NVMET_PORTS, list[n]->d_name, NQN_HDR_STR, hostname, device); - if (access(path2, F_OK) != SUCCESS) { - rc = symlink(path, path2); - if (rc != SUCCESS) { - msg = "Error. Unable to create link of NQN to port. %s: symlink: %s"; - print_error(msg, return_message, __func__, strerror(errno)); - list = clean_scandir(list, err); - return rc; - } + sprintf(path, "%s/%s%s-%s", SYS_NVMET_TGT, NQN_HDR_STR, hostname, device); + sprintf(path2, "%s/%s/subsystems/%s%s-%s", SYS_NVMET_PORTS, list[n]->d_name, NQN_HDR_STR, hostname, device); + if (access(path2, F_OK) != SUCCESS) { + rc = symlink(path, path2); + if (rc != SUCCESS) { + msg = "Error. Unable to create link of NQN to port. %s: symlink: %s"; + print_error(msg, return_message, __func__, strerror(errno)); + list = clean_scandir(list, err); + return rc; } } } From 525daef7b056b921c1ac5a08f4f9ca60ff6a7e07 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Sat, 14 Jan 2023 02:38:56 +0000 Subject: [PATCH 09/10] Updated changelog. --- CHANGELOG.md | 1 + pkg/debian/changelog | 1 + pkg/rpm/rapiddisk.spec.rhel | 1 + pkg/rpm/rapiddisk.spec.sles | 1 + src/common.h | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4943627..02b77d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). - utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). - utility: Fix resize operation error messaging (github issue #142). +- utility: Cleaned up and optimized NVMe Target management. - scripts: Fixed error checking in NVMe Target hostnqn script file. - scripts: Added fio execution script file examples. - scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/pkg/debian/changelog b/pkg/debian/changelog index a1da527..2528d81 100644 --- a/pkg/debian/changelog +++ b/pkg/debian/changelog @@ -15,6 +15,7 @@ rapiddisk (9.0.0-1) UNRELEASED; urgency=medium * utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). * utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). * utility: Fix resize operation error messaging (github issue #142). + * utility: Cleaned up and optimized NVMe Target management. * scripts: Fixed error checking in NVMe Target hostnqn script file. * scripts: Added fio execution script file examples. * scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/pkg/rpm/rapiddisk.spec.rhel b/pkg/rpm/rapiddisk.spec.rhel index 99c8573..db9b494 100644 --- a/pkg/rpm/rapiddisk.spec.rhel +++ b/pkg/rpm/rapiddisk.spec.rhel @@ -123,6 +123,7 @@ rm -rf %{buildroot} - utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). - utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). - utility: Fix resize operation error messaging (github issue #142). +- utility: Cleaned up and optimized NVMe Target management. - scripts: Fixed error checking in NVMe Target hostnqn script file. - scripts: Added fio execution script file examples. - scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/pkg/rpm/rapiddisk.spec.sles b/pkg/rpm/rapiddisk.spec.sles index e38ab1f..7600aef 100644 --- a/pkg/rpm/rapiddisk.spec.sles +++ b/pkg/rpm/rapiddisk.spec.sles @@ -123,6 +123,7 @@ rm -rf %{buildroot} - utility: Fix forking logic in daemon and remove need for realpath() usage (thank you Matteo Tenca). - utility: Define and standardize error messaging for consistency and improve verbose mode (thank you Matteo Tenca). - utility: Fix resize operation error messaging (github issue #142). +- utility: Cleaned up and optimized NVMe Target management. - scripts: Fixed error checking in NVMe Target hostnqn script file. - scripts: Added fio execution script file examples. - scripts: Added valgrind test script to check for memory leaks (thank you Matteo Tenca). diff --git a/src/common.h b/src/common.h index ffee82c..4d65671 100644 --- a/src/common.h +++ b/src/common.h @@ -90,7 +90,7 @@ typedef char bool; #define ERR_SIGPIPE_HANDLER "Failed to install SIGPIPE handler: %s, %s" #define ERR_INVALID_MODE "Invalid cache mode in URL." #define ERR_DEV_NOEXIST "Error. Device %s does not exist." -#define ERR_PORT_NOEXIST "Error. Port %d does not exist." +#define ERR_PORT_NOEXIST "Error. Port %d does not exist." #define ERR_CACHE_TGT_NOEXIST "Error. Cache target %s does not exist." /** From 524c3293bfc4034a2c9f77427e542505b17f9e04 Mon Sep 17 00:00:00 2001 From: Matteo Tenca <93343338+matteotenca@users.noreply.github.com> Date: Sat, 21 Jan 2023 04:15:35 +0100 Subject: [PATCH 10/10] Fix a wrong function call and some memory leaks in nvmet.c In nvmet_export_volume(), nvmet_scan_ports() is called to get the existing port list, but the function does not return all of them. Switched to nvmet_scan_all_ports(). In nvmet_enable_port(), some function calls to free resources were missing. --- src/nvmet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/nvmet.c b/src/nvmet.c index 92c668c..d16402b 100644 --- a/src/nvmet.c +++ b/src/nvmet.c @@ -564,7 +564,7 @@ int nvmet_export_volume(struct RD_PROFILE *rd_prof, RC_PROFILE *rc_prof, char *d rc = INVALID_VALUE; if (port != INVALID_VALUE) { - ports = nvmet_scan_ports(return_message); + ports = nvmet_scan_all_ports(return_message); if ((ports == NULL) && (strlen(return_message) != 0)) { msg = "%s"; print_error(msg, return_message, return_message); @@ -1116,6 +1116,7 @@ int nvmet_enable_port(char *interface, int port, int protocol, char *return_mess if (access(path, F_OK) == SUCCESS) { msg = "Error. NVMe Target Port %d already exists."; print_error(msg, return_message, port); + free_nvmet_linked_lists(ports, NULL); return rc; } @@ -1123,6 +1124,7 @@ int nvmet_enable_port(char *interface, int port, int protocol, char *return_mess if (ipaddr == NULL) { msg = "Cannot find the IP address of interface %s. Error: %s"; print_error(msg, return_message, interface, error_message); + free_nvmet_linked_lists(ports, NULL); return INVALID_VALUE; } sprintf(ip, "%s", ipaddr); @@ -1130,6 +1132,7 @@ int nvmet_enable_port(char *interface, int port, int protocol, char *return_mess if (ip_validate(ip) != SUCCESS) { msg = "Error. IP address %s is invalid."; print_error(msg, return_message, ip); + free_nvmet_linked_lists(ports, NULL); return rc; }