1686 lines
58 KiB
Diff
1686 lines
58 KiB
Diff
From b0b6f77b3c75ca881bf21771f629c0716378ece2 Mon Sep 17 00:00:00 2001
|
|
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
Date: Mon, 29 Jan 2018 13:56:17 +0100
|
|
Subject: [PATCH 1/4] Add the NVDIMM plugin
|
|
|
|
Add a new plugin for working with the NVDIMM devices. Currently
|
|
only namespace management is supported.
|
|
---
|
|
Makefile.am | 1 +
|
|
configure.ac | 6 +
|
|
dist/libblockdev.spec.in | 48 +++-
|
|
docs/libblockdev-docs.xml.in | 1 +
|
|
docs/libblockdev-sections.txt | 22 ++
|
|
src/lib/Makefile.am | 3 +-
|
|
src/lib/blockdev.c.in | 14 +-
|
|
src/lib/plugin_apis/nvdimm.api | 206 ++++++++++++++
|
|
src/lib/plugins.h | 1 +
|
|
src/plugins/Makefile.am | 16 ++
|
|
src/plugins/nvdimm.c | 544 ++++++++++++++++++++++++++++++++++++
|
|
src/plugins/nvdimm.h | 76 +++++
|
|
src/python/gi/overrides/BlockDev.py | 43 +++
|
|
13 files changed, 977 insertions(+), 4 deletions(-)
|
|
create mode 100644 src/lib/plugin_apis/nvdimm.api
|
|
create mode 100644 src/plugins/nvdimm.c
|
|
create mode 100644 src/plugins/nvdimm.h
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index ad41c1b..d30acd1 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -41,6 +41,7 @@ PLUGINS = btrfs \
|
|
lvm \
|
|
mdraid \
|
|
mpath \
|
|
+ nvdimm \
|
|
part \
|
|
s390 \
|
|
swap
|
|
diff --git a/configure.ac b/configure.ac
|
|
index d41a307..4206afa 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -141,6 +141,7 @@ LIBBLOCKDEV_PLUGIN([SWAP], [swap])
|
|
LIBBLOCKDEV_PLUGIN([KBD], [kbd])
|
|
LIBBLOCKDEV_PLUGIN([PART], [part])
|
|
LIBBLOCKDEV_PLUGIN([FS], [fs])
|
|
+LIBBLOCKDEV_PLUGIN([NVDIMM], [nvdimm])
|
|
|
|
AM_CONDITIONAL(WITH_PART_O_WITH_FS, test "x$with_part" != "xno" -o "x$with_fs" != "xno")
|
|
|
|
@@ -194,6 +195,11 @@ AS_IF([test "x$with_btrfs" != "xno" -o "x$with_mdraid" != "xno" -o "x$with_kbd"
|
|
[LIBBLOCKDEV_PKG_CHECK_MODULES([BYTESIZE], [bytesize >= 0.1])],
|
|
[])
|
|
|
|
+AS_IF([test "x$with_nvdimm" != "xno"],
|
|
+ [LIBBLOCKDEV_PKG_CHECK_MODULES([UUID], [uuid])
|
|
+ LIBBLOCKDEV_PKG_CHECK_MODULES([NDCTL], [libndctl])]
|
|
+ [])
|
|
+
|
|
AC_SUBST([skip_patterns], [$skip_patterns])
|
|
AC_SUBST([MAJOR_VER], [\"2\"])
|
|
|
|
diff --git a/dist/libblockdev.spec.in b/dist/libblockdev.spec.in
|
|
index b23bb5b..5e2f52b 100644
|
|
--- a/dist/libblockdev.spec.in
|
|
+++ b/dist/libblockdev.spec.in
|
|
@@ -13,6 +13,7 @@
|
|
%define with_kbd @WITH_KBD@
|
|
%define with_part @WITH_PART@
|
|
%define with_fs @WITH_FS@
|
|
+%define with_nvdimm @WITH_NVDIMM@
|
|
%define with_gi @WITH_GI@
|
|
|
|
# python3 is not available on older RHEL
|
|
@@ -59,11 +60,14 @@
|
|
%if %{with_fs} != 1
|
|
%define fs_copts --without-fs
|
|
%endif
|
|
+%if %{with_nvdimm} != 1
|
|
+%define nvdimm_copts --without-nvdimm
|
|
+%endif
|
|
%if %{with_gi} != 1
|
|
%define gi_copts --disable-introspection
|
|
%endif
|
|
|
|
-%define configure_opts %{?distro_copts} %{?btrfs_copts} %{?crypto_copts} %{?dm_copts} %{?loop_copts} %{?lvm_copts} %{?lvm_dbus_copts} %{?mdraid_copts} %{?mpath_copts} %{?swap_copts} %{?kbd_copts} %{?part_copts} %{?fs_copts} %{?gi_copts}
|
|
+%define configure_opts %{?distro_copts} %{?btrfs_copts} %{?crypto_copts} %{?dm_copts} %{?loop_copts} %{?lvm_copts} %{?lvm_dbus_copts} %{?mdraid_copts} %{?mpath_copts} %{?swap_copts} %{?kbd_copts} %{?part_copts} %{?fs_copts} %{?nvdimm_copts} %{?gi_copts}
|
|
|
|
Name: libblockdev
|
|
Version: 2.16
|
|
@@ -394,6 +398,29 @@ This package contains header files and pkg-config files needed for development
|
|
with the libblockdev-mpath plugin/library.
|
|
%endif
|
|
|
|
+%if %{with_nvdimm}
|
|
+%package nvdimm
|
|
+BuildRequires: ndctl-devel
|
|
+BuildRequires: libuuid-devel
|
|
+Summary: The NVDIMM plugin for the libblockdev library
|
|
+Requires: %{name}-utils%{?_isa} >= 0.11
|
|
+Requires: ndctl
|
|
+
|
|
+%description nvdimm
|
|
+The libblockdev library plugin (and in the same time a standalone library)
|
|
+providing the functionality related to operations with NVDIMM devices.
|
|
+
|
|
+%package nvdimm-devel
|
|
+Summary: Development files for the libblockdev-nvdimm plugin/library
|
|
+Requires: %{name}-nvdimm%{?_isa} = %{version}-%{release}
|
|
+Requires: %{name}-utils-devel%{?_isa}
|
|
+Requires: glib2-devel
|
|
+
|
|
+%description nvdimm-devel
|
|
+This package contains header files and pkg-config files needed for development
|
|
+with the libblockdev-nvdimm plugin/library.
|
|
+%endif
|
|
+
|
|
|
|
%if %{with_part}
|
|
%package part
|
|
@@ -502,6 +529,10 @@ Requires: %{name}-mdraid%{?_isa} = %{version}-%{release}
|
|
Requires: %{name}-mpath%{?_isa} = %{version}-%{release}
|
|
%endif
|
|
|
|
+%if %{with_nvdimm}
|
|
+Requires: %{name}-nvdimm%{?_isa} = %{version}-%{release}
|
|
+%endif
|
|
+
|
|
%if %{with_part}
|
|
Requires: %{name}-part%{?_isa} = %{version}-%{release}
|
|
%endif
|
|
@@ -580,6 +611,10 @@ find %{buildroot} -type f -name "*.la" | xargs %{__rm}
|
|
%postun mpath -p /sbin/ldconfig
|
|
%endif
|
|
|
|
+%if %{with_nvdimm}
|
|
+%ldconfig_scriptlets nvdimm
|
|
+%endif
|
|
+
|
|
%if %{with_part}
|
|
%post part -p /sbin/ldconfig
|
|
%postun part -p /sbin/ldconfig
|
|
@@ -765,6 +800,17 @@ find %{buildroot} -type f -name "*.la" | xargs %{__rm}
|
|
%endif
|
|
|
|
|
|
+%if %{with_nvdimm}
|
|
+%files nvdimm
|
|
+%{_libdir}/libbd_nvdimm.so.*
|
|
+
|
|
+%files nvdimm-devel
|
|
+%{_libdir}/libbd_nvdimm.so
|
|
+%dir %{_includedir}/blockdev
|
|
+%{_includedir}/blockdev/nvdimm.h
|
|
+%endif
|
|
+
|
|
+
|
|
%if %{with_part}
|
|
%files part
|
|
%{_libdir}/libbd_part.so.*
|
|
diff --git a/docs/libblockdev-docs.xml.in b/docs/libblockdev-docs.xml.in
|
|
index a758657..98aa0bf 100644
|
|
--- a/docs/libblockdev-docs.xml.in
|
|
+++ b/docs/libblockdev-docs.xml.in
|
|
@@ -29,6 +29,7 @@
|
|
<xi:include href="xml/lvm.xml"/>
|
|
<xi:include href="xml/mdraid.xml"/>
|
|
<xi:include href="xml/mpath.xml"/>
|
|
+ <xi:include href="xml/nvdimm.xml"/>
|
|
<xi:include href="xml/plugins.xml"/>
|
|
<xi:include href="xml/part.xml"/>
|
|
<xi:include href="xml/swap.xml"/>
|
|
diff --git a/docs/libblockdev-sections.txt b/docs/libblockdev-sections.txt
|
|
index cc0ae7a..756b5b5 100644
|
|
--- a/docs/libblockdev-sections.txt
|
|
+++ b/docs/libblockdev-sections.txt
|
|
@@ -565,3 +565,25 @@ BDS390Tech
|
|
BDS390TechMode
|
|
bd_s390_is_tech_avail
|
|
</SECTION>
|
|
+
|
|
+<SECTION>
|
|
+<FILE>nvdimm</FILE>
|
|
+bd_nvdimm_check_deps
|
|
+bd_nvdimm_close
|
|
+bd_nvdimm_init
|
|
+bd_nvdimm_error_quark
|
|
+BD_NVDIMM_ERROR
|
|
+BDNVDIMMError
|
|
+BDNVDIMMNamespaceMode
|
|
+BDNVDIMMNamespaceInfo
|
|
+bd_nvdimm_namespace_get_mode_from_str
|
|
+bd_nvdimm_namespace_get_mode_str
|
|
+bd_nvdimm_namespace_enable
|
|
+bd_nvdimm_namespace_disable
|
|
+bd_nvdimm_namespace_info
|
|
+bd_nvdimm_list_namespaces
|
|
+bd_nvdimm_namespace_reconfigure
|
|
+BDNVDIMMTech
|
|
+BDNVDIMMTechMode
|
|
+bd_nvdimm_is_tech_avail
|
|
+</SECTION>
|
|
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
|
|
index e020703..d9a91ca 100644
|
|
--- a/src/lib/Makefile.am
|
|
+++ b/src/lib/Makefile.am
|
|
@@ -30,7 +30,8 @@ GIHEADERS = ${builddir}/plugin_apis/kbd.h \
|
|
${builddir}/plugin_apis/loop.h \
|
|
${builddir}/plugin_apis/mpath.h \
|
|
${builddir}/plugin_apis/part.h \
|
|
- ${builddir}/plugin_apis/fs.h
|
|
+ ${builddir}/plugin_apis/fs.h \
|
|
+ ${builddir}/plugin_apis/nvdimm.h
|
|
|
|
GIHEADERS += $(wildcard ${srcdir}/../utils/*.[ch])
|
|
GIHEADERS += blockdev.c blockdev.h plugins.c plugins.h
|
|
diff --git a/src/lib/blockdev.c.in b/src/lib/blockdev.c.in
|
|
index 2aeeac2..fd36fee 100644
|
|
--- a/src/lib/blockdev.c.in
|
|
+++ b/src/lib/blockdev.c.in
|
|
@@ -25,6 +25,8 @@
|
|
#include "plugin_apis/part.c"
|
|
#include "plugin_apis/fs.h"
|
|
#include "plugin_apis/fs.c"
|
|
+#include "plugin_apis/nvdimm.h"
|
|
+#include "plugin_apis/nvdimm.c"
|
|
|
|
#if defined(__s390__) || defined(__s390x__)
|
|
#include "plugin_apis/s390.h"
|
|
@@ -59,7 +61,8 @@ static gchar * default_plugin_so[BD_PLUGIN_UNDEF] = {
|
|
"libbd_crypto.so."@MAJOR_VER@, "libbd_mpath.so."@MAJOR_VER@,
|
|
"libbd_dm.so."@MAJOR_VER@, "libbd_mdraid.so."@MAJOR_VER@,
|
|
"libbd_kbd.so."@MAJOR_VER@,"libbd_s390.so."@MAJOR_VER@,
|
|
- "libbd_part.so."@MAJOR_VER@, "libbd_fs.so."@MAJOR_VER@
|
|
+ "libbd_part.so."@MAJOR_VER@, "libbd_fs.so."@MAJOR_VER@,
|
|
+ "libbd_nvdimm.so."@MAJOR_VER@
|
|
};
|
|
static BDPluginStatus plugins[BD_PLUGIN_UNDEF] = {
|
|
{{BD_PLUGIN_LVM, NULL}, NULL},
|
|
@@ -74,9 +77,10 @@ static BDPluginStatus plugins[BD_PLUGIN_UNDEF] = {
|
|
{{BD_PLUGIN_S390, NULL}, NULL},
|
|
{{BD_PLUGIN_PART, NULL}, NULL},
|
|
{{BD_PLUGIN_FS, NULL}, NULL},
|
|
+ {{BD_PLUGIN_NVDIMM, NULL}, NULL},
|
|
};
|
|
static gchar* plugin_names[BD_PLUGIN_UNDEF] = {
|
|
- "lvm", "btrfs", "swap", "loop", "crypto", "mpath", "dm", "mdraid", "kbd", "s390", "part", "fs"
|
|
+ "lvm", "btrfs", "swap", "loop", "crypto", "mpath", "dm", "mdraid", "kbd", "s390", "part", "fs", "nvdimm"
|
|
};
|
|
|
|
static void set_plugin_so_name (BDPlugin name, const gchar *so_name) {
|
|
@@ -226,6 +230,10 @@ static void unload_plugins () {
|
|
if (plugins[BD_PLUGIN_FS].handle && !unload_fs (plugins[BD_PLUGIN_FS].handle))
|
|
g_warning ("Failed to close the fs plugin");
|
|
plugins[BD_PLUGIN_FS].handle = NULL;
|
|
+
|
|
+ if (plugins[BD_PLUGIN_NVDIMM].handle && !unload_nvdimm (plugins[BD_PLUGIN_NVDIMM].handle))
|
|
+ g_warning ("Failed to close the nvdimm plugin");
|
|
+ plugins[BD_PLUGIN_NVDIMM].handle = NULL;
|
|
}
|
|
|
|
static void load_plugin_from_sonames (BDPlugin plugin, LoadFunc load_fn, void **handle, GSList *sonames) {
|
|
@@ -264,6 +272,8 @@ static void do_load (GSList **plugins_sonames) {
|
|
load_plugin_from_sonames (BD_PLUGIN_PART, load_part_from_plugin, &(plugins[BD_PLUGIN_PART].handle), plugins_sonames[BD_PLUGIN_PART]);
|
|
if (!plugins[BD_PLUGIN_FS].handle && plugins_sonames[BD_PLUGIN_FS])
|
|
load_plugin_from_sonames (BD_PLUGIN_FS, load_fs_from_plugin, &(plugins[BD_PLUGIN_FS].handle), plugins_sonames[BD_PLUGIN_FS]);
|
|
+ if (!plugins[BD_PLUGIN_NVDIMM].handle && plugins_sonames[BD_PLUGIN_NVDIMM])
|
|
+ load_plugin_from_sonames (BD_PLUGIN_NVDIMM, load_nvdimm_from_plugin, &(plugins[BD_PLUGIN_NVDIMM].handle), plugins_sonames[BD_PLUGIN_NVDIMM]);
|
|
}
|
|
|
|
static gboolean load_plugins (BDPluginSpec **require_plugins, gboolean reload, guint64 *num_loaded) {
|
|
diff --git a/src/lib/plugin_apis/nvdimm.api b/src/lib/plugin_apis/nvdimm.api
|
|
new file mode 100644
|
|
index 0000000..3d74f62
|
|
--- /dev/null
|
|
+++ b/src/lib/plugin_apis/nvdimm.api
|
|
@@ -0,0 +1,206 @@
|
|
+#include <glib.h>
|
|
+#include <glib-object.h>
|
|
+#include <blockdev/utils.h>
|
|
+
|
|
+#ifndef BD_NVDIMM_API
|
|
+#define BD_NVDIMM_API
|
|
+
|
|
+GQuark bd_nvdimm_error_quark (void) {
|
|
+ return g_quark_from_static_string ("g-bd-nvdimm-error-quark");
|
|
+}
|
|
+
|
|
+#define BD_NVDIMM_ERROR bd_nvdimm_error_quark ()
|
|
+typedef enum {
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_PARSE,
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_NOEXIST,
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_MODE_INVAL
|
|
+} BDNVDIMMError;
|
|
+
|
|
+typedef enum {
|
|
+ BD_NVDIMM_NAMESPACE_MODE_RAW,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_SECTOR,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_MEMORY,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_DAX,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_UNKNOWN
|
|
+} BDNVDIMMNamespaceMode;
|
|
+
|
|
+#define BD_NVDIMM_TYPE_NAMESPACE_INFO (bd_nvdimm_namespace_info_get_type ())
|
|
+GType bd_nvdimm_namespace_info_get_type();
|
|
+
|
|
+/**
|
|
+ * BDNVDIMMNamespaceInfo:
|
|
+ * @dev: namespace device name ("namespaceX.Y")
|
|
+ * @mode: mode of the namespace (BDNVDIMMNamespaceMode)
|
|
+ * @size: size of the namespace
|
|
+ * @uuid: UUID of the namespace
|
|
+ * @sector_size: sector size of the namespace (0 for non-sector namespaces)
|
|
+ * @blockdev: name of the block device for the namespace
|
|
+ * @enabled: whether the namespace is enabled or not
|
|
+ */
|
|
+typedef struct BDNVDIMMNamespaceInfo {
|
|
+ gchar *dev;
|
|
+ guint64 mode;
|
|
+ guint64 size;
|
|
+ gchar *uuid;
|
|
+ guint64 sector_size;
|
|
+ gchar *blockdev;
|
|
+ gboolean enabled;
|
|
+} BDNVDIMMNamespaceInfo;
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_info_free: (skip)
|
|
+ *
|
|
+ * Frees @info.
|
|
+ */
|
|
+void bd_nvdimm_namespace_info_free (BDNVDIMMNamespaceInfo *info) {
|
|
+ g_free (info->dev);
|
|
+ g_free (info->uuid);
|
|
+ g_free (info->blockdev);
|
|
+ g_free (info);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_info_copy: (skip)
|
|
+ *
|
|
+ * Creates a new copy of @info.
|
|
+ */
|
|
+BDNVDIMMNamespaceInfo* bd_nvdimm_namespace_info_copy (BDNVDIMMNamespaceInfo *info) {
|
|
+ BDNVDIMMNamespaceInfo *new_info = g_new0 (BDNVDIMMNamespaceInfo, 1);
|
|
+
|
|
+ new_info->dev = info->dev;
|
|
+ new_info->mode = info->mode;
|
|
+ new_info->size = info->size;
|
|
+ new_info->uuid = g_strdup (info->uuid);
|
|
+ new_info->sector_size = info->sector_size;
|
|
+ new_info->blockdev = g_strdup (info->blockdev);
|
|
+ new_info->enabled = info->enabled;
|
|
+
|
|
+ return new_info;
|
|
+}
|
|
+
|
|
+GType bd_nvdimm_namespace_info_get_type () {
|
|
+ static GType type = 0;
|
|
+
|
|
+ if (G_UNLIKELY(type == 0)) {
|
|
+ type = g_boxed_type_register_static("BDNVDIMMNamespaceInfo",
|
|
+ (GBoxedCopyFunc) bd_nvdimm_namespace_info_copy,
|
|
+ (GBoxedFreeFunc) bd_nvdimm_namespace_info_free);
|
|
+ }
|
|
+
|
|
+ return type;
|
|
+}
|
|
+
|
|
+typedef enum {
|
|
+ BD_NVDIMM_TECH_NAMESPACE = 0,
|
|
+} BDNVDIMMTech;
|
|
+
|
|
+typedef enum {
|
|
+ BD_NVDIMM_TECH_MODE_CREATE = 1 << 0,
|
|
+ BD_NVDIMM_TECH_MODE_REMOVE = 1 << 1,
|
|
+ BD_NVDIMM_TECH_MODE_ACTIVATE_DEACTIVATE = 1 << 2,
|
|
+ BD_NVDIMM_TECH_MODE_QUERY = 1 << 3,
|
|
+ BD_NVDIMM_TECH_MODE_RECONFIGURE = 1 << 4,
|
|
+} BDNVDIMMTechMode;
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_is_tech_avail:
|
|
+ * @tech: the queried tech
|
|
+ * @mode: a bit mask of queried modes of operation (#BDNVDIMMTechMode) for @tech
|
|
+ * @error: (out): place to store error (details about why the @tech-@mode combination is not available)
|
|
+ *
|
|
+ * Returns: whether the @tech-@mode combination is available -- supported by the
|
|
+ * plugin implementation and having all the runtime dependencies available
|
|
+ */
|
|
+gboolean bd_nvdimm_is_tech_avail (BDNVDIMMTech tech, guint64 mode, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_get_mode_from_str:
|
|
+ * @mode_str: string representation of mode
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: mode matching the @mode_str given or %BD_NVDIMM_NAMESPACE_MODE_UNKNOWN in case of no match
|
|
+ *
|
|
+ * Tech category: always available
|
|
+ */
|
|
+BDNVDIMMNamespaceMode bd_nvdimm_namespace_get_mode_from_str (const gchar *mode_str, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_get_mode_str:
|
|
+ * @mode: mode to get string representation of
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (transfer none): string representation of @mode or %NULL in case of error
|
|
+ *
|
|
+ * Tech category: always available
|
|
+ */
|
|
+const gchar* bd_nvdimm_namespace_get_mode_str (BDNVDIMMNamespaceMode mode, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_enable:
|
|
+ * @namespace: name of the namespace to enable
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: whether the @namespace was successfully enabled or not
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_ACTIVATE_DEACTIVATE
|
|
+ */
|
|
+gboolean bd_nvdimm_namespace_enable (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_disable:
|
|
+ * @namespace: name of the namespace to disable
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: whether the @namespace was successfully disabled or not
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_ACTIVATE_DEACTIVATE
|
|
+ */
|
|
+gboolean bd_nvdimm_namespace_disable (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_info:
|
|
+ * @namespace: namespace to get information about
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (transfer full): information about given namespace or %NULL if no such
|
|
+ * namespace was found (@error may be set to indicate error)
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_QUERY
|
|
+ */
|
|
+BDNVDIMMNamespaceInfo* bd_nvdimm_namespace_info (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_list_namespaces:
|
|
+ * @bus: (allow-none): return only namespaces on given bus (specified by name),
|
|
+ * %NULL may be specified to return namespaces from all buses
|
|
+ * @region: (allow-none): return only namespaces on given region (specified by regionX name or region id),
|
|
+ * %NULL may be specified to return namespaces from all regions
|
|
+ * @idle: whether to list idle (not enabled) namespaces too
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now
|
|
+ * passed to the 'ndctl' utility)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (array zero-terminated=1): information about the namespaces on @bus and @region or
|
|
+ * %NULL if no namespaces were found (@error may be set to indicate error)
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_QUERY
|
|
+ */
|
|
+BDNVDIMMNamespaceInfo** bd_nvdimm_list_namespaces (const gchar *bus, const gchar *region, gboolean idle, const BDExtraArg **extra, GError **error);
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_reconfigure:
|
|
+ * @namespace: name of the namespace to recofigure
|
|
+ * @mode: mode type to set (memory/sector/raw/dax)
|
|
+ * @error: (out): place to store error if any
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now
|
|
+ * passed to the 'ndctl' utility)
|
|
+ *
|
|
+ * Returns: whether @namespace was successfully reconfigured or not
|
|
+ */
|
|
+gboolean bd_nvdimm_namespace_reconfigure (const gchar* namespace, BDNVDIMMNamespaceMode mode, gboolean force, const BDExtraArg **extra, GError** error);
|
|
+
|
|
+#endif /* BD_NVDIMM_API */
|
|
diff --git a/src/lib/plugins.h b/src/lib/plugins.h
|
|
index 48d2217..9bc9799 100644
|
|
--- a/src/lib/plugins.h
|
|
+++ b/src/lib/plugins.h
|
|
@@ -17,6 +17,7 @@ typedef enum {
|
|
BD_PLUGIN_S390,
|
|
BD_PLUGIN_PART,
|
|
BD_PLUGIN_FS,
|
|
+ BD_PLUGIN_NVDIMM,
|
|
BD_PLUGIN_UNDEF
|
|
} BDPlugin;
|
|
|
|
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
|
|
index b69c8f7..d11bdca 100644
|
|
--- a/src/plugins/Makefile.am
|
|
+++ b/src/plugins/Makefile.am
|
|
@@ -36,6 +36,10 @@ if WITH_MPATH
|
|
lib_LTLIBRARIES += libbd_mpath.la
|
|
endif
|
|
|
|
+if WITH_NVDIMM
|
|
+lib_LTLIBRARIES += libbd_nvdimm.la
|
|
+endif
|
|
+
|
|
if WITH_SWAP
|
|
lib_LTLIBRARIES += libbd_swap.la
|
|
endif
|
|
@@ -122,6 +126,14 @@ libbd_mpath_la_CPPFLAGS = -I${builddir}/../../include/
|
|
libbd_mpath_la_SOURCES = mpath.c mpath.h check_deps.c check_deps.h
|
|
endif
|
|
|
|
+if WITH_NVDIMM
|
|
+libbd_nvdimm_la_CFLAGS = $(GLIB_CFLAGS) $(UUID_CFLAGS) $(NDCTL_CFLAGS) -Wall -Wextra -Werror
|
|
+libbd_nvdimm_la_LIBADD = $(GLIB_LIBS) $(UUID_LIBS) $(NDCTL_LIBS) ${builddir}/../utils/libbd_utils.la
|
|
+libbd_nvdimm_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 2:0:0 -Wl,--no-undefined
|
|
+libbd_nvdimm_la_CPPFLAGS = -I${builddir}/../../include/
|
|
+libbd_nvdimm_la_SOURCES = nvdimm.c nvdimm.h check_deps.c check_deps.h
|
|
+endif
|
|
+
|
|
if WITH_SWAP
|
|
libbd_swap_la_CFLAGS = $(GLIB_CFLAGS) -Wall -Wextra -Werror
|
|
libbd_swap_la_LIBADD = $(GLIB_LIBS) ${builddir}/../utils/libbd_utils.la
|
|
@@ -194,6 +206,10 @@ if WITH_MPATH
|
|
libinclude_HEADERS += mpath.h
|
|
endif
|
|
|
|
+if WITH_NVDIMM
|
|
+libinclude_HEADERS += nvdimm.h
|
|
+endif
|
|
+
|
|
if WITH_SWAP
|
|
libinclude_HEADERS += swap.h
|
|
endif
|
|
diff --git a/src/plugins/nvdimm.c b/src/plugins/nvdimm.c
|
|
new file mode 100644
|
|
index 0000000..7a6802a
|
|
--- /dev/null
|
|
+++ b/src/plugins/nvdimm.c
|
|
@@ -0,0 +1,544 @@
|
|
+/*
|
|
+ * Copyright (C) 2018 Red Hat, Inc.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * Author: Vojtech Trefny <vtrefny@redhat.com>
|
|
+ */
|
|
+
|
|
+#include <glib.h>
|
|
+#include <blockdev/utils.h>
|
|
+#include <ndctl/libndctl.h>
|
|
+#include <uuid.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include "nvdimm.h"
|
|
+#include "check_deps.h"
|
|
+
|
|
+/**
|
|
+ * SECTION: nvdimm
|
|
+ * @short_description: plugin for operations with nvdimm space
|
|
+ * @title: NVDIMM
|
|
+ * @include: nvdimm.h
|
|
+ *
|
|
+ * A plugin for operations with NVDIMM devices.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_error_quark: (skip)
|
|
+ */
|
|
+GQuark bd_nvdimm_error_quark (void) {
|
|
+ return g_quark_from_static_string ("g-bd-nvdimm-error-quark");
|
|
+}
|
|
+
|
|
+void bd_nvdimm_namespace_info_free (BDNVDIMMNamespaceInfo *info) {
|
|
+ g_free (info->dev);
|
|
+ g_free (info->uuid);
|
|
+ g_free (info->blockdev);
|
|
+ g_free (info);
|
|
+}
|
|
+
|
|
+BDNVDIMMNamespaceInfo* bd_nvdimm_namespace_info_copy (BDNVDIMMNamespaceInfo *info) {
|
|
+ BDNVDIMMNamespaceInfo *new_info = g_new0 (BDNVDIMMNamespaceInfo, 1);
|
|
+
|
|
+ new_info->dev = g_strdup (info->dev);
|
|
+ new_info->mode = info->mode;
|
|
+ new_info->size = info->size;
|
|
+ new_info->uuid = g_strdup (info->uuid);
|
|
+ new_info->sector_size = info->sector_size;
|
|
+ new_info->blockdev = g_strdup (info->blockdev);
|
|
+ new_info->enabled = info->enabled;
|
|
+
|
|
+ return new_info;
|
|
+}
|
|
+
|
|
+
|
|
+static const gchar * const mode_str[BD_NVDIMM_NAMESPACE_MODE_UNKNOWN+1] = {"raw", "sector", "memory", "dax", "unknown"};
|
|
+
|
|
+static volatile guint avail_deps = 0;
|
|
+static GMutex deps_check_lock;
|
|
+
|
|
+#define DEPS_NDCTL 0
|
|
+#define DEPS_NDCTL_MASK (1 << DEPS_NDCTL)
|
|
+#define DEPS_LAST 1
|
|
+
|
|
+static UtilDep deps[DEPS_LAST] = {
|
|
+ {"ndctl", NULL, NULL, NULL},
|
|
+};
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_check_deps:
|
|
+ *
|
|
+ * Returns: whether the plugin's runtime dependencies are satisfied or not
|
|
+ *
|
|
+ * Function checking plugin's runtime dependencies.
|
|
+ *
|
|
+ */
|
|
+gboolean bd_nvdimm_check_deps () {
|
|
+ GError *error = NULL;
|
|
+ guint i = 0;
|
|
+ gboolean status = FALSE;
|
|
+ gboolean ret = TRUE;
|
|
+
|
|
+ for (i=0; i < DEPS_LAST; i++) {
|
|
+ status = bd_utils_check_util_version (deps[i].name, deps[i].version,
|
|
+ deps[i].ver_arg, deps[i].ver_regexp, &error);
|
|
+ if (!status)
|
|
+ g_warning ("%s", error->message);
|
|
+ else
|
|
+ g_atomic_int_or (&avail_deps, 1 << i);
|
|
+ g_clear_error (&error);
|
|
+ ret = ret && status;
|
|
+ }
|
|
+
|
|
+ if (!ret)
|
|
+ g_warning("Cannot load the NVDIMM plugin");
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_init:
|
|
+ *
|
|
+ * Initializes the plugin. **This function is called automatically by the
|
|
+ * library's initialization functions.**
|
|
+ *
|
|
+ */
|
|
+gboolean bd_nvdimm_init () {
|
|
+ /* nothing to do here */
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_close:
|
|
+ *
|
|
+ * Cleans up after the plugin. **This function is called automatically by the
|
|
+ * library's functions that unload it.**
|
|
+ *
|
|
+ */
|
|
+void bd_nvdimm_close () {
|
|
+ /* nothing to do here */
|
|
+ return;
|
|
+}
|
|
+
|
|
+#define UNUSED __attribute__((unused))
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_is_tech_avail:
|
|
+ * @tech: the queried tech
|
|
+ * @mode: a bit mask of queried modes of operation (#BDNVDIMMTechMode) for @tech
|
|
+ * @error: (out): place to store error (details about why the @tech-@mode combination is not available)
|
|
+ *
|
|
+ * Returns: whether the @tech-@mode combination is available -- supported by the
|
|
+ * plugin implementation and having all the runtime dependencies available
|
|
+ */
|
|
+gboolean bd_nvdimm_is_tech_avail (BDNVDIMMTech tech, guint64 mode, GError **error) {
|
|
+ /* all tech-mode combinations are supported by this implementation of the
|
|
+ plugin, namespace reconfigure requires the 'ndctl' utility */
|
|
+
|
|
+ if (tech == BD_NVDIMM_TECH_NAMESPACE) {
|
|
+ if (mode & BD_NVDIMM_TECH_MODE_RECONFIGURE)
|
|
+ return check_deps (&avail_deps, DEPS_NDCTL_MASK, deps, DEPS_LAST, &deps_check_lock, error);
|
|
+ else
|
|
+ return TRUE;
|
|
+ } else {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_TECH_UNAVAIL, "Unknown technology");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_get_mode_from_str:
|
|
+ * @mode_str: string representation of mode
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: mode matching the @mode_str given or %BD_NVDIMM_NAMESPACE_MODE_UNKNOWN in case of no match
|
|
+ *
|
|
+ * Tech category: always available
|
|
+ */
|
|
+BDNVDIMMNamespaceMode bd_nvdimm_namespace_get_mode_from_str (const gchar *mode_str, GError **error) {
|
|
+ if (g_strcmp0 (mode_str, "raw") == 0)
|
|
+ return BD_NVDIMM_NAMESPACE_MODE_RAW;
|
|
+ else if (g_strcmp0 (mode_str, "sector") == 0)
|
|
+ return BD_NVDIMM_NAMESPACE_MODE_SECTOR;
|
|
+ else if (g_strcmp0 (mode_str, "memory") == 0)
|
|
+ return BD_NVDIMM_NAMESPACE_MODE_MEMORY;
|
|
+ else if (g_strcmp0 (mode_str, "dax") == 0)
|
|
+ return BD_NVDIMM_NAMESPACE_MODE_DAX;
|
|
+ else {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_MODE_INVAL,
|
|
+ "Invalid mode given: '%s'", mode_str);
|
|
+ return BD_NVDIMM_NAMESPACE_MODE_UNKNOWN;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_get_mode_str:
|
|
+ * @mode: mode to get string representation of
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (transfer none): string representation of @mode or %NULL in case of error
|
|
+ *
|
|
+ * Tech category: always available
|
|
+ */
|
|
+const gchar* bd_nvdimm_namespace_get_mode_str (BDNVDIMMNamespaceMode mode, GError **error) {
|
|
+ if (mode <= BD_NVDIMM_NAMESPACE_MODE_UNKNOWN)
|
|
+ return mode_str[mode];
|
|
+ else {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_MODE_INVAL,
|
|
+ "Invalid mode given: %d", mode);
|
|
+ return NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+static struct ndctl_namespace* get_namespace_by_name (const gchar *namespace, struct ndctl_ctx *ctx) {
|
|
+ struct ndctl_namespace *ndns = NULL;
|
|
+ struct ndctl_region *region = NULL;
|
|
+ struct ndctl_bus *bus = NULL;
|
|
+
|
|
+ ndctl_bus_foreach (ctx, bus) {
|
|
+ ndctl_region_foreach (bus, region) {
|
|
+ ndctl_namespace_foreach (region, ndns) {
|
|
+ if (g_strcmp0 (namespace, ndctl_namespace_get_devname (ndns)) == 0)
|
|
+ return ndns;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_enable:
|
|
+ * @namespace: name of the namespace to enable
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: whether the @namespace was successfully enabled or not
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_ACTIVATE_DEACTIVATE
|
|
+ */
|
|
+gboolean bd_nvdimm_namespace_enable (const gchar *namespace, const BDExtraArg **extra UNUSED, GError **error) {
|
|
+ struct ndctl_ctx *ctx = NULL;
|
|
+ struct ndctl_namespace *ndns = NULL;
|
|
+ gint ret = 0;
|
|
+
|
|
+ ret = ndctl_new (&ctx);
|
|
+ if (ret != 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to create ndctl context");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ndns = get_namespace_by_name (namespace, ctx);
|
|
+ if (!ndns) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_NOEXIST,
|
|
+ "Failed to enable namespace: namespace '%s' not found.", namespace);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ret = ndctl_namespace_enable (ndns);
|
|
+ if (ret < 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to enable namespace: %s", strerror (-ret));
|
|
+ ndctl_unref (ctx);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ndctl_unref (ctx);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_disable:
|
|
+ * @namespace: name of the namespace to disable
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: whether the @namespace was successfully disabled or not
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_ACTIVATE_DEACTIVATE
|
|
+ */
|
|
+gboolean bd_nvdimm_namespace_disable (const gchar *namespace, const BDExtraArg **extra UNUSED, GError **error) {
|
|
+ struct ndctl_ctx *ctx = NULL;
|
|
+ struct ndctl_namespace *ndns = NULL;
|
|
+ gint ret = 0;
|
|
+
|
|
+ ret = ndctl_new (&ctx);
|
|
+ if (ret != 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to create ndctl context");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ndns = get_namespace_by_name (namespace, ctx);
|
|
+ if (!ndns) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_NOEXIST,
|
|
+ "Failed to disable namespace: namespace '%s' not found.", namespace);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ret = ndctl_namespace_disable_safe (ndns);
|
|
+ if (ret != 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to disable namespace: %s", strerror (-ret));
|
|
+ ndctl_unref (ctx);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ndctl_unref (ctx);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BDNVDIMMNamespaceInfo* get_nvdimm_namespace_info (struct ndctl_namespace *ndns, GError **error) {
|
|
+ struct ndctl_btt *btt;
|
|
+ struct ndctl_pfn *pfn;
|
|
+ struct ndctl_dax *dax;
|
|
+ enum ndctl_namespace_mode mode;
|
|
+ gchar uuid_buf[37] = {0};
|
|
+ uuid_t uuid;
|
|
+
|
|
+ btt = ndctl_namespace_get_btt (ndns);
|
|
+ dax = ndctl_namespace_get_dax (ndns);
|
|
+ pfn = ndctl_namespace_get_pfn (ndns);
|
|
+ mode = ndctl_namespace_get_mode (ndns);
|
|
+
|
|
+ BDNVDIMMNamespaceInfo *info = g_new0 (BDNVDIMMNamespaceInfo, 1);
|
|
+
|
|
+ info->dev = g_strdup (ndctl_namespace_get_devname (ndns));
|
|
+
|
|
+ switch (mode) {
|
|
+ case NDCTL_NS_MODE_MEMORY:
|
|
+ if (pfn)
|
|
+ info->size = ndctl_pfn_get_size (pfn);
|
|
+ else
|
|
+ info->size = ndctl_namespace_get_size (ndns);
|
|
+ info->mode = BD_NVDIMM_NAMESPACE_MODE_MEMORY;
|
|
+ break;
|
|
+ case NDCTL_NS_MODE_DAX:
|
|
+ if (!dax) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to get information about namespaces: DAX mode "
|
|
+ "detected but no DAX device found.");
|
|
+ bd_nvdimm_namespace_info_free (info);
|
|
+ return NULL;
|
|
+ }
|
|
+ info->size = ndctl_dax_get_size (dax);
|
|
+ info->mode = BD_NVDIMM_NAMESPACE_MODE_DAX;
|
|
+ break;
|
|
+ case NDCTL_NS_MODE_SAFE:
|
|
+ if (!btt) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to get information about namespaces: Sector mode "
|
|
+ "detected but no BTT device found.");
|
|
+ bd_nvdimm_namespace_info_free (info);
|
|
+ return NULL;
|
|
+ }
|
|
+ info->size = ndctl_btt_get_size (btt);
|
|
+ info->mode = BD_NVDIMM_NAMESPACE_MODE_SECTOR;
|
|
+ break;
|
|
+ case NDCTL_NS_MODE_RAW:
|
|
+ info->size = ndctl_namespace_get_size (ndns);
|
|
+ info->mode = BD_NVDIMM_NAMESPACE_MODE_RAW;
|
|
+ break;
|
|
+ default:
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to get information about namespaces: Unknow mode.");
|
|
+ bd_nvdimm_namespace_info_free (info);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (btt) {
|
|
+ ndctl_btt_get_uuid (btt, uuid);
|
|
+ uuid_unparse (uuid, uuid_buf);
|
|
+ info->uuid = g_strdup (uuid_buf);
|
|
+
|
|
+ info->sector_size = ndctl_btt_get_sector_size (btt);
|
|
+ info->blockdev = g_strdup (ndctl_btt_get_block_device (btt));
|
|
+ } else if (pfn) {
|
|
+ ndctl_pfn_get_uuid (pfn, uuid);
|
|
+ uuid_unparse (uuid, uuid_buf);
|
|
+ info->uuid = g_strdup (uuid_buf);
|
|
+
|
|
+ info->sector_size = 0; // no sector size for memory mode
|
|
+ info->blockdev = g_strdup (ndctl_pfn_get_block_device (pfn));
|
|
+ } else if (dax) {
|
|
+ ndctl_dax_get_uuid (dax, uuid);
|
|
+ uuid_unparse (uuid, uuid_buf);
|
|
+ info->uuid = g_strdup (uuid_buf);
|
|
+
|
|
+ /* no sector size or blockdev for dax mode */
|
|
+ info->sector_size = 0;
|
|
+ info->blockdev = NULL;
|
|
+ } else {
|
|
+ ndctl_namespace_get_uuid (ndns, uuid);
|
|
+
|
|
+ if (uuid_is_null (uuid))
|
|
+ info->uuid = NULL;
|
|
+ else {
|
|
+ uuid_unparse (uuid, uuid_buf);
|
|
+ info->uuid = g_strdup (uuid_buf);
|
|
+ }
|
|
+
|
|
+ info->sector_size = 0; // no sector size for raw mode
|
|
+ info->blockdev = g_strdup (ndctl_namespace_get_block_device (ndns));
|
|
+ }
|
|
+
|
|
+ info->enabled = ndctl_namespace_is_active (ndns);
|
|
+
|
|
+ return info;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_info:
|
|
+ * @namespace: namespace to get information about
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (transfer full): information about given namespace or %NULL if no such
|
|
+ * namespace was found (@error may be set to indicate error)
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_QUERY
|
|
+ */
|
|
+BDNVDIMMNamespaceInfo* bd_nvdimm_namespace_info (const gchar *namespace, const BDExtraArg **extra UNUSED, GError **error) {
|
|
+ struct ndctl_ctx *ctx = NULL;
|
|
+ struct ndctl_namespace *ndns = NULL;
|
|
+ BDNVDIMMNamespaceInfo *info = NULL;
|
|
+ gint ret = 0;
|
|
+
|
|
+ ret = ndctl_new (&ctx);
|
|
+ if (ret != 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to create ndctl context");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ndns = get_namespace_by_name (namespace, ctx);
|
|
+ if (ndns) {
|
|
+ info = get_nvdimm_namespace_info (ndns, error);
|
|
+ ndctl_unref (ctx);
|
|
+ return info;
|
|
+ }
|
|
+
|
|
+ ndctl_unref (ctx);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_list_namespaces:
|
|
+ * @bus_name: (allow-none): return only namespaces on given bus (specified by name),
|
|
+ * %NULL may be specified to return namespaces from all buses
|
|
+ * @region_name: (allow-none): return only namespaces on given region (specified by 'regionX' name),
|
|
+ * %NULL may be specified to return namespaces from all regions
|
|
+ * @idle: whether to list idle (not enabled) namespaces too
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (array zero-terminated=1): information about the namespaces on @bus and @region or
|
|
+ * %NULL if no namespaces were found (@error may be set to indicate error)
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_QUERY
|
|
+ */
|
|
+BDNVDIMMNamespaceInfo** bd_nvdimm_list_namespaces (const gchar *bus_name, const gchar *region_name, gboolean idle, const BDExtraArg **extra UNUSED, GError **error) {
|
|
+ struct ndctl_ctx *ctx = NULL;
|
|
+ struct ndctl_namespace *ndns = NULL;
|
|
+ struct ndctl_region *region = NULL;
|
|
+ struct ndctl_bus *bus = NULL;
|
|
+ gint ret = 0;
|
|
+ BDNVDIMMNamespaceInfo **info = NULL;
|
|
+
|
|
+ GPtrArray *namespaces = g_ptr_array_new ();
|
|
+
|
|
+ ret = ndctl_new (&ctx);
|
|
+ if (ret != 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to create ndctl context");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ndctl_bus_foreach (ctx, bus) {
|
|
+ if (bus_name && g_strcmp0 (bus_name, ndctl_bus_get_devname (bus)) != 0)
|
|
+ continue;
|
|
+
|
|
+ ndctl_region_foreach (bus, region) {
|
|
+ if (region_name && g_strcmp0 (bus_name, ndctl_region_get_devname (region)) != 0)
|
|
+ continue;
|
|
+
|
|
+ ndctl_namespace_foreach (region, ndns) {
|
|
+ if (!idle && !ndctl_namespace_is_active (ndns))
|
|
+ continue;
|
|
+
|
|
+ BDNVDIMMNamespaceInfo *info = get_nvdimm_namespace_info (ndns, error);
|
|
+ if (!info) {
|
|
+ g_ptr_array_foreach (namespaces, (GFunc) (void *) bd_nvdimm_namespace_info_free, NULL);
|
|
+ g_ptr_array_free (namespaces, FALSE);
|
|
+ ndctl_unref (ctx);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ g_ptr_array_add (namespaces, info);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (namespaces->len == 0) {
|
|
+ ndctl_unref (ctx);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ g_ptr_array_add (namespaces, NULL);
|
|
+
|
|
+ info = (BDNVDIMMNamespaceInfo **) g_ptr_array_free (namespaces, FALSE);
|
|
+ ndctl_unref (ctx);
|
|
+
|
|
+ return info;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bd_nvdimm_namespace_reconfigure:
|
|
+ * @namespace: name of the namespace to recofigure
|
|
+ * @mode: mode type to set
|
|
+ * @error: (out): place to store error if any
|
|
+ * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now
|
|
+ * passed to the 'ndctl' utility)
|
|
+ *
|
|
+ * Returns: whether @namespace was successfully reconfigured or not
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_RECONFIGURE
|
|
+ */
|
|
+gboolean bd_nvdimm_namespace_reconfigure (const gchar* namespace, BDNVDIMMNamespaceMode mode, gboolean force, const BDExtraArg **extra, GError** error) {
|
|
+ const gchar *args[8] = {"ndctl", "create-namespace", "-e", namespace, "-m", NULL, NULL, NULL};
|
|
+ gboolean ret = FALSE;
|
|
+ const gchar *mode_str = NULL;
|
|
+
|
|
+ if (!check_deps (&avail_deps, DEPS_NDCTL_MASK, deps, DEPS_LAST, &deps_check_lock, error))
|
|
+ return FALSE;
|
|
+
|
|
+ mode_str = bd_nvdimm_namespace_get_mode_str (mode, error);
|
|
+ if (!mode_str)
|
|
+ /* error is already populated */
|
|
+ return FALSE;
|
|
+
|
|
+ args[5] = g_strdup (mode_str);
|
|
+
|
|
+ if (force)
|
|
+ args[6] = "-f";
|
|
+
|
|
+ ret = bd_utils_exec_and_report_error (args, extra, error);
|
|
+
|
|
+ g_free ((gchar *) args[5]);
|
|
+ return ret;
|
|
+}
|
|
diff --git a/src/plugins/nvdimm.h b/src/plugins/nvdimm.h
|
|
new file mode 100644
|
|
index 0000000..5a1642f
|
|
--- /dev/null
|
|
+++ b/src/plugins/nvdimm.h
|
|
@@ -0,0 +1,76 @@
|
|
+#include <glib.h>
|
|
+#include <blockdev/utils.h>
|
|
+
|
|
+#ifndef BD_NVDIMM
|
|
+#define BD_NVDIMM
|
|
+
|
|
+GQuark bd_nvdimm_error_quark (void);
|
|
+#define BD_NVDIMM_ERROR bd_nvdimm_error_quark ()
|
|
+typedef enum {
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_PARSE,
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_NOEXIST,
|
|
+ BD_NVDIMM_ERROR_NAMESPACE_MODE_INVAL,
|
|
+ BD_NVDIMM_ERROR_TECH_UNAVAIL,
|
|
+} BDNVDIMMError;
|
|
+
|
|
+typedef enum {
|
|
+ BD_NVDIMM_NAMESPACE_MODE_RAW,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_SECTOR,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_MEMORY,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_DAX,
|
|
+ BD_NVDIMM_NAMESPACE_MODE_UNKNOWN
|
|
+} BDNVDIMMNamespaceMode;
|
|
+
|
|
+typedef struct BDNVDIMMNamespaceInfo {
|
|
+ gchar *dev;
|
|
+ guint64 mode;
|
|
+ guint64 size;
|
|
+ gchar *uuid;
|
|
+ guint64 sector_size;
|
|
+ gchar *blockdev;
|
|
+ gboolean enabled;
|
|
+} BDNVDIMMNamespaceInfo;
|
|
+
|
|
+void bd_nvdimm_namespace_info_free (BDNVDIMMNamespaceInfo *info);
|
|
+BDNVDIMMNamespaceInfo* bd_nvdimm_namespace_info_copy (BDNVDIMMNamespaceInfo *info);
|
|
+
|
|
+typedef enum {
|
|
+ BD_NVDIMM_TECH_NAMESPACE = 0,
|
|
+} BDNVDIMMTech;
|
|
+
|
|
+typedef enum {
|
|
+ BD_NVDIMM_TECH_MODE_CREATE = 1 << 0,
|
|
+ BD_NVDIMM_TECH_MODE_REMOVE = 1 << 1,
|
|
+ BD_NVDIMM_TECH_MODE_ACTIVATE_DEACTIVATE = 1 << 2,
|
|
+ BD_NVDIMM_TECH_MODE_QUERY = 1 << 3,
|
|
+ BD_NVDIMM_TECH_MODE_RECONFIGURE = 1 << 4,
|
|
+} BDNVDIMMTechMode;
|
|
+
|
|
+/*
|
|
+ * If using the plugin as a standalone library, the following functions should
|
|
+ * be called to:
|
|
+ *
|
|
+ * check_deps() - check plugin's dependencies, returning TRUE if satisfied
|
|
+ * init() - initialize the plugin, returning TRUE on success
|
|
+ * close() - clean after the plugin at the end or if no longer used
|
|
+ *
|
|
+ */
|
|
+gboolean bd_nvdimm_check_deps ();
|
|
+gboolean bd_nvdimm_init ();
|
|
+void bd_nvdimm_close ();
|
|
+
|
|
+gboolean bd_nvdimm_is_tech_avail (BDNVDIMMTech tech, guint64 mode, GError **error);
|
|
+
|
|
+BDNVDIMMNamespaceMode bd_nvdimm_namespace_get_mode_from_str (const gchar *mode_str, GError **error);
|
|
+const gchar* bd_nvdimm_namespace_get_mode_str (BDNVDIMMNamespaceMode mode, GError **error);
|
|
+
|
|
+gboolean bd_nvdimm_namespace_enable (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
+gboolean bd_nvdimm_namespace_disable (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
+
|
|
+BDNVDIMMNamespaceInfo* bd_nvdimm_namespace_info (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
+BDNVDIMMNamespaceInfo** bd_nvdimm_list_namespaces (const gchar *bus, const gchar *region, gboolean idle, const BDExtraArg **extra, GError **error);
|
|
+
|
|
+gboolean bd_nvdimm_namespace_reconfigure (const gchar* namespace, BDNVDIMMNamespaceMode mode, gboolean force, const BDExtraArg **extra, GError** error);
|
|
+
|
|
+#endif /* BD_CRYPTO */
|
|
diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py
|
|
index fb3ffb4..dc634ab 100644
|
|
--- a/src/python/gi/overrides/BlockDev.py
|
|
+++ b/src/python/gi/overrides/BlockDev.py
|
|
@@ -50,6 +50,7 @@ bd_plugins = { "lvm": BlockDev.Plugin.LVM,
|
|
"part": BlockDev.Plugin.PART,
|
|
"fs": BlockDev.Plugin.FS,
|
|
"s390": BlockDev.Plugin.S390,
|
|
+ "nvdimm": BlockDev.Plugin.NVDIMM,
|
|
}
|
|
|
|
|
|
@@ -692,6 +693,41 @@ def part_create_table(disk, type, ignore_existing=True):
|
|
__all__.append("part_create_table")
|
|
|
|
|
|
+_nvdimm_namespace_reconfigure = BlockDev.nvdimm_namespace_reconfigure
|
|
+@override(BlockDev.nvdimm_namespace_reconfigure)
|
|
+def nvdimm_namespace_reconfigure(namespace, mode, force=False, extra=None, **kwargs):
|
|
+ extra = _get_extra(extra, kwargs)
|
|
+ return _nvdimm_namespace_reconfigure(namespace, mode, force, extra)
|
|
+__all__.append("nvdimm_namespace_reconfigure")
|
|
+
|
|
+_nvdimm_namespace_info = BlockDev.nvdimm_namespace_info
|
|
+@override(BlockDev.nvdimm_namespace_info)
|
|
+def nvdimm_namespace_info(namespace, extra=None, **kwargs):
|
|
+ extra = _get_extra(extra, kwargs)
|
|
+ return _nvdimm_namespace_info(namespace, extra)
|
|
+__all__.append("nvdimm_namespace_info")
|
|
+
|
|
+_nvdimm_list_namespaces = BlockDev.nvdimm_list_namespaces
|
|
+@override(BlockDev.nvdimm_list_namespaces)
|
|
+def nvdimm_list_namespaces(bus=None, region=None, idle=False, extra=None, **kwargs):
|
|
+ extra = _get_extra(extra, kwargs)
|
|
+ return _nvdimm_list_namespaces(bus, region, idle, extra)
|
|
+__all__.append("nvdimm_list_namespaces")
|
|
+
|
|
+_nvdimm_namespace_enable = BlockDev.nvdimm_namespace_enable
|
|
+@override(BlockDev.nvdimm_namespace_enable)
|
|
+def nvdimm_namespace_enable(namespace, extra=None, **kwargs):
|
|
+ extra = _get_extra(extra, kwargs)
|
|
+ return _nvdimm_namespace_enable(namespace, extra)
|
|
+__all__.append("nvdimm_namespace_enable")
|
|
+
|
|
+_nvdimm_namespace_disable = BlockDev.nvdimm_namespace_disable
|
|
+@override(BlockDev.nvdimm_namespace_disable)
|
|
+def nvdimm_namespace_disable(namespace, extra=None, **kwargs):
|
|
+ extra = _get_extra(extra, kwargs)
|
|
+ return _nvdimm_namespace_disable(namespace, extra)
|
|
+__all__.append("nvdimm_namespace_disable")
|
|
+
|
|
## defined in this overrides only!
|
|
def plugin_specs_from_names(plugin_names):
|
|
ret = []
|
|
@@ -886,6 +922,10 @@ class UtilsError(BlockDevError):
|
|
pass
|
|
__all__.append("UtilsError")
|
|
|
|
+class NVDIMMError(BlockDevError):
|
|
+ pass
|
|
+__all__.append("NVDIMMError")
|
|
+
|
|
class BlockDevNotImplementedError(NotImplementedError, BlockDevError):
|
|
pass
|
|
__all__.append("BlockDevNotImplementedError")
|
|
@@ -927,6 +967,9 @@ __all__.append("part")
|
|
fs = ErrorProxy("fs", BlockDev, [(GLib.Error, FSError)], [not_implemented_rule, fs_nofs_rule])
|
|
__all__.append("fs")
|
|
|
|
+nvdimm = ErrorProxy("nvdimm", BlockDev, [(GLib.Error, NVDIMMError)], [not_implemented_rule])
|
|
+__all__.append("nvdimm")
|
|
+
|
|
s390 = ErrorProxy("s390", BlockDev, [(GLib.Error, S390Error)], [not_implemented_rule])
|
|
__all__.append("s390")
|
|
|
|
--
|
|
1.8.3.1
|
|
|
|
|
|
From 2fda30f62f962eb9e10894b4d919acd013c9c93b Mon Sep 17 00:00:00 2001
|
|
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
Date: Wed, 31 Jan 2018 16:27:59 +0100
|
|
Subject: [PATCH 2/4] Add tests for the NVDIMM plugin
|
|
|
|
---
|
|
tests/nvdimm_test.py | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 178 insertions(+)
|
|
create mode 100644 tests/nvdimm_test.py
|
|
|
|
diff --git a/tests/nvdimm_test.py b/tests/nvdimm_test.py
|
|
new file mode 100644
|
|
index 0000000..b4eb43d
|
|
--- /dev/null
|
|
+++ b/tests/nvdimm_test.py
|
|
@@ -0,0 +1,178 @@
|
|
+import json
|
|
+import os
|
|
+import unittest
|
|
+import overrides_hack
|
|
+
|
|
+from utils import run_command, read_file, skip_on, fake_path
|
|
+from gi.repository import BlockDev, GLib
|
|
+
|
|
+
|
|
+@skip_on("debian", reason="NVDIMM plugin doesn't work on Debian (missing ndctl)")
|
|
+class NVDIMMTestCase(unittest.TestCase):
|
|
+
|
|
+ requested_plugins = BlockDev.plugin_specs_from_names(("nvdimm",))
|
|
+
|
|
+ @classmethod
|
|
+ def setUpClass(cls):
|
|
+ if not BlockDev.is_initialized():
|
|
+ BlockDev.init(cls.requested_plugins, None)
|
|
+ else:
|
|
+ BlockDev.reinit(cls.requested_plugins, True, None)
|
|
+
|
|
+class NVDIMMNamespaceTestCase(NVDIMMTestCase):
|
|
+
|
|
+ sys_info = None
|
|
+
|
|
+ def _get_nvdimm_info(self):
|
|
+ ret, out, _err = run_command("ndctl list")
|
|
+ if ret != 0 or not out:
|
|
+ return None
|
|
+
|
|
+ decoder = json.JSONDecoder()
|
|
+ decoded = decoder.decode(out)
|
|
+ return decoded
|
|
+
|
|
+ def setUp(self):
|
|
+ self.sys_info = self._get_nvdimm_info()
|
|
+ if not self.sys_info:
|
|
+ self.skipTest("No NVDIMM devices available.")
|
|
+
|
|
+ # skip the test if there is more than one device
|
|
+ # these tests change nvdimm mode a we need to be sure that we are really
|
|
+ # working with the 'fake' device created by the memmap kernel cmdline option
|
|
+ if type(self.sys_info) is not dict:
|
|
+ self.skipTest("Multiple NVDIMM devices found.")
|
|
+
|
|
+ # skip the tests if the nvdimm is a 'fake' one
|
|
+ cmdline = read_file("/proc/cmdline")
|
|
+ if "memmap=" not in cmdline:
|
|
+ self.skipTest("NVDIMM device found, but not created by the 'memmap' kernel command-line option.")
|
|
+
|
|
+ def _check_namespace_info(self, bd_info):
|
|
+ self.assertEqual(bd_info.dev, self.sys_info["dev"])
|
|
+ self.assertEqual(bd_info.mode, BlockDev.nvdimm_namespace_get_mode_from_str(self.sys_info["mode"]))
|
|
+ self.assertEqual(bd_info.size, self.sys_info["size"])
|
|
+
|
|
+ if "uuid" in self.sys_info.keys():
|
|
+ self.assertEqual(bd_info.uuid, self.sys_info["uuid"])
|
|
+ else:
|
|
+ self.assertIsNone(bd_info.uuid)
|
|
+
|
|
+ if "blockdev" in self.sys_info.keys():
|
|
+ self.assertEqual(bd_info.blockdev, self.sys_info["blockdev"])
|
|
+ else:
|
|
+ self.assertIsNone(bd_info.blockdev)
|
|
+
|
|
+ if "sector_size" in self.sys_info.keys():
|
|
+ self.assertEqual(bd_info.sector_size, self.sys_info["sector_size"])
|
|
+ else:
|
|
+ self.assertEqual(bd_info.sector_size, 0)
|
|
+
|
|
+ def test_namespace_info(self):
|
|
+ # get info about our 'testing' namespace
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self._check_namespace_info(info)
|
|
+
|
|
+ info = BlockDev.nvdimm_namespace_info("definitely-not-a-namespace")
|
|
+ self.assertIsNone(info)
|
|
+
|
|
+ def test_list_namespaces(self):
|
|
+ bd_namespaces = BlockDev.nvdimm_list_namespaces()
|
|
+ self.assertEqual(len(bd_namespaces), 1)
|
|
+
|
|
+ self._check_namespace_info(bd_namespaces[0])
|
|
+
|
|
+ @unittest.skipUnless("JENKINS_HOME" in os.environ, "skipping test that modifies system configuration")
|
|
+ def test_enable_disable(self):
|
|
+ # non-existing/unknow namespace
|
|
+ with self.assertRaises(GLib.GError):
|
|
+ BlockDev.nvdimm_namespace_enable("definitely-not-a-namespace")
|
|
+
|
|
+ # enable the namespace
|
|
+ ret = BlockDev.nvdimm_namespace_enable(self.sys_info["dev"])
|
|
+ self.assertTrue(ret)
|
|
+
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self.assertTrue(info.enabled)
|
|
+
|
|
+ # disable the namespace
|
|
+ ret = BlockDev.nvdimm_namespace_disable(self.sys_info["dev"])
|
|
+ self.assertTrue(ret)
|
|
+
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self.assertFalse(info.enabled)
|
|
+
|
|
+ # and enable it again
|
|
+ ret = BlockDev.nvdimm_namespace_enable(self.sys_info["dev"])
|
|
+ self.assertTrue(ret)
|
|
+
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self.assertTrue(info.enabled)
|
|
+
|
|
+ @unittest.skipUnless("JENKINS_HOME" in os.environ, "skipping test that modifies system configuration")
|
|
+ def test_namespace_reconfigure(self):
|
|
+ # active namespace -- reconfigure doesn't work without force
|
|
+ with self.assertRaises(GLib.GError):
|
|
+ BlockDev.nvdimm_namespace_reconfigure(self.sys_info["dev"],
|
|
+ BlockDev.NVDIMMNamespaceMode.SECTOR,
|
|
+ False)
|
|
+
|
|
+ # non-existing/unknow mode
|
|
+ with self.assertRaises(GLib.GError):
|
|
+ BlockDev.nvdimm_namespace_reconfigure(self.sys_info["dev"],
|
|
+ BlockDev.NVDIMMNamespaceMode.UNKNOWN,
|
|
+ True)
|
|
+
|
|
+ # non-existing/unknow namespace
|
|
+ with self.assertRaises(GLib.GError):
|
|
+ BlockDev.nvdimm_namespace_reconfigure("definitely-not-a-namespace",
|
|
+ BlockDev.NVDIMMNamespaceMode.SECTOR,
|
|
+ True)
|
|
+
|
|
+ # switch to sector mode
|
|
+ ret = BlockDev.nvdimm_namespace_reconfigure(self.sys_info["dev"],
|
|
+ BlockDev.NVDIMMNamespaceMode.SECTOR,
|
|
+ True, extra={"-l": "512"})
|
|
+ self.assertTrue(ret)
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self.assertEqual(info.mode, BlockDev.NVDIMMNamespaceMode.SECTOR)
|
|
+
|
|
+ # and now to memory mode
|
|
+ ret = BlockDev.nvdimm_namespace_reconfigure(self.sys_info["dev"],
|
|
+ BlockDev.NVDIMMNamespaceMode.MEMORY,
|
|
+ True)
|
|
+ self.assertTrue(ret)
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self.assertEqual(info.mode, BlockDev.NVDIMMNamespaceMode.MEMORY)
|
|
+
|
|
+ # and back to sector
|
|
+ ret = BlockDev.nvdimm_namespace_reconfigure(self.sys_info["dev"],
|
|
+ BlockDev.NVDIMMNamespaceMode.SECTOR,
|
|
+ True, extra={"-l": "512"})
|
|
+ self.assertTrue(ret)
|
|
+ info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
+ self.assertEqual(info.mode, BlockDev.NVDIMMNamespaceMode.SECTOR)
|
|
+
|
|
+
|
|
+class NVDIMMUnloadTest(NVDIMMTestCase):
|
|
+ def setUp(self):
|
|
+ # make sure the library is initialized with all plugins loaded for other
|
|
+ # tests
|
|
+ self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
|
|
+
|
|
+ def test_check_no_ndctl(self):
|
|
+ """Verify that checking ndctl tool availability works as expected"""
|
|
+
|
|
+ # unload all plugins first
|
|
+ self.assertTrue(BlockDev.reinit([], True, None))
|
|
+
|
|
+ with fake_path(all_but="ndctl"):
|
|
+ # no ndctl tool available, the NVDIMM plugin should fail to load
|
|
+ with self.assertRaises(GLib.GError):
|
|
+ BlockDev.reinit(self.requested_plugins, True, None)
|
|
+
|
|
+ self.assertNotIn("nvdimm", BlockDev.get_available_plugin_names())
|
|
+
|
|
+ # load the plugins back
|
|
+ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
|
|
+ self.assertIn("nvdimm", BlockDev.get_available_plugin_names())
|
|
--
|
|
1.8.3.1
|
|
|
|
|
|
From 333bad8ceafc229b9a8c97df23715a02361aee01 Mon Sep 17 00:00:00 2001
|
|
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
Date: Thu, 1 Feb 2018 14:46:51 +0100
|
|
Subject: [PATCH 3/4] Add --without-xyz to DISTCHECK_CONFIGURE_FLAGS for
|
|
disabled plugins
|
|
|
|
We need to disable these plugins for distcheck because of missing
|
|
build dependecies etc.
|
|
---
|
|
Makefile.am | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 53 insertions(+)
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index d30acd1..54b89e1 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -4,6 +4,59 @@ SHELL = /bin/bash
|
|
ACLOCAL_AMFLAGS = -I m4
|
|
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
|
|
|
+if !WITH_BTRFS
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-btrfs
|
|
+endif
|
|
+
|
|
+if !WITH_CRYPTO
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-crypto
|
|
+endif
|
|
+
|
|
+if !WITH_DM
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-dm
|
|
+endif
|
|
+
|
|
+if !WITH_LOOP
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-loop
|
|
+endif
|
|
+
|
|
+if !WITH_LVM
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-lvm
|
|
+endif
|
|
+
|
|
+if !WITH_LVM_DBUS
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-lvm-dbus
|
|
+endif
|
|
+
|
|
+if !WITH_MDRAID
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-mdraid
|
|
+endif
|
|
+
|
|
+if !WITH_MPATH
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-mpath
|
|
+endif
|
|
+
|
|
+if !WITH_NVDIMM
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-nvdimm
|
|
+endif
|
|
+
|
|
+if !WITH_SWAP
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-swap
|
|
+endif
|
|
+
|
|
+if !WITH_KBD
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-kbd
|
|
+endif
|
|
+
|
|
+if !WITH_PART
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-part
|
|
+endif
|
|
+
|
|
+if !WITH_S390
|
|
+DISTCHECK_CONFIGURE_FLAGS += --without-s390
|
|
+endif
|
|
+
|
|
+
|
|
SUBDIRS = include src dist scripts data
|
|
if WITH_GTK_DOC
|
|
SUBDIRS += docs
|
|
--
|
|
1.8.3.1
|
|
|
|
|
|
From 7ebc9d20fa8b97482a109121dd016e01c4d032e4 Mon Sep 17 00:00:00 2001
|
|
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
Date: Tue, 6 Feb 2018 14:56:10 +0100
|
|
Subject: [PATCH 4/4] Add function for getting NVDIMM namespace name from
|
|
devname or path
|
|
|
|
For example getting "namespace0.0" from "pmem0" or "/dev/pmem0".
|
|
---
|
|
docs/libblockdev-sections.txt | 1 +
|
|
src/lib/plugin_apis/nvdimm.api | 13 +++++++++
|
|
src/plugins/nvdimm.c | 63 ++++++++++++++++++++++++++++++++++++++++++
|
|
src/plugins/nvdimm.h | 2 ++
|
|
tests/nvdimm_test.py | 8 ++++++
|
|
5 files changed, 87 insertions(+)
|
|
|
|
diff --git a/docs/libblockdev-sections.txt b/docs/libblockdev-sections.txt
|
|
index 756b5b5..8aaa290 100644
|
|
--- a/docs/libblockdev-sections.txt
|
|
+++ b/docs/libblockdev-sections.txt
|
|
@@ -578,6 +578,7 @@ BDNVDIMMNamespaceMode
|
|
BDNVDIMMNamespaceInfo
|
|
bd_nvdimm_namespace_get_mode_from_str
|
|
bd_nvdimm_namespace_get_mode_str
|
|
+bd_nvdimm_namespace_get_devname
|
|
bd_nvdimm_namespace_enable
|
|
bd_nvdimm_namespace_disable
|
|
bd_nvdimm_namespace_info
|
|
diff --git a/src/lib/plugin_apis/nvdimm.api b/src/lib/plugin_apis/nvdimm.api
|
|
index 3d74f62..9d5260c 100644
|
|
--- a/src/lib/plugin_apis/nvdimm.api
|
|
+++ b/src/lib/plugin_apis/nvdimm.api
|
|
@@ -137,6 +137,19 @@ BDNVDIMMNamespaceMode bd_nvdimm_namespace_get_mode_from_str (const gchar *mode_s
|
|
const gchar* bd_nvdimm_namespace_get_mode_str (BDNVDIMMNamespaceMode mode, GError **error);
|
|
|
|
/**
|
|
+ * bd_nvdimm_namespace_get_devname:
|
|
+ * @device: name or path of a block device (e.g. "/dev/pmem0")
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (transfer full): namespace device name (e.g. "namespaceX.Y") for @device
|
|
+ * or %NULL if @device is not a NVDIMM namespace
|
|
+ * (@error may be set to indicate error)
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_QUERY
|
|
+ */
|
|
+gchar* bd_nvdimm_namespace_get_devname (const gchar *device, GError **error);
|
|
+
|
|
+/**
|
|
* bd_nvdimm_namespace_enable:
|
|
* @namespace: name of the namespace to enable
|
|
* @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
diff --git a/src/plugins/nvdimm.c b/src/plugins/nvdimm.c
|
|
index 7a6802a..40ade05 100644
|
|
--- a/src/plugins/nvdimm.c
|
|
+++ b/src/plugins/nvdimm.c
|
|
@@ -222,6 +222,69 @@ static struct ndctl_namespace* get_namespace_by_name (const gchar *namespace, st
|
|
}
|
|
|
|
/**
|
|
+ * bd_nvdimm_namespace_get_devname:
|
|
+ * @device: name or path of a block device (e.g. "/dev/pmem0")
|
|
+ * @error: (out): place to store error (if any)
|
|
+ *
|
|
+ * Returns: (transfer full): namespace device name (e.g. "namespaceX.Y") for @device
|
|
+ * or %NULL if @device is not a NVDIMM namespace
|
|
+ * (@error may be set to indicate error)
|
|
+ *
|
|
+ * Tech category: %BD_NVDIMM_TECH_NAMESPACE-%BD_NVDIMM_TECH_MODE_QUERY
|
|
+ */
|
|
+gchar* bd_nvdimm_namespace_get_devname (const gchar *device, GError **error) {
|
|
+ struct ndctl_ctx *ctx = NULL;
|
|
+ struct ndctl_namespace *ndns = NULL;
|
|
+ struct ndctl_region *region = NULL;
|
|
+ struct ndctl_bus *bus = NULL;
|
|
+ gint success = 0;
|
|
+ gchar *ret = NULL;
|
|
+
|
|
+ /* get rid of the "/dev/" prefix (if any) */
|
|
+ if (g_str_has_prefix (device, "/dev/"))
|
|
+ device = device + 5;
|
|
+
|
|
+ success = ndctl_new (&ctx);
|
|
+ if (success != 0) {
|
|
+ g_set_error (error, BD_NVDIMM_ERROR, BD_NVDIMM_ERROR_NAMESPACE_FAIL,
|
|
+ "Failed to create ndctl context");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ ndctl_bus_foreach (ctx, bus) {
|
|
+ ndctl_region_foreach (bus, region) {
|
|
+ ndctl_namespace_foreach (region, ndns) {
|
|
+ if (!ndctl_namespace_is_active (ndns))
|
|
+ continue;
|
|
+
|
|
+ struct ndctl_btt *btt = ndctl_namespace_get_btt (ndns);
|
|
+ struct ndctl_dax *dax = ndctl_namespace_get_dax (ndns);
|
|
+ struct ndctl_pfn *pfn = ndctl_namespace_get_pfn (ndns);
|
|
+ const gchar *blockdev = NULL;
|
|
+
|
|
+ if (dax)
|
|
+ continue;
|
|
+ else if (btt)
|
|
+ blockdev = ndctl_btt_get_block_device (btt);
|
|
+ else if (pfn)
|
|
+ blockdev = ndctl_pfn_get_block_device (pfn);
|
|
+ else
|
|
+ blockdev = ndctl_namespace_get_block_device (ndns);
|
|
+
|
|
+ if (g_strcmp0 (blockdev, device) == 0) {
|
|
+ ret = g_strdup (ndctl_namespace_get_devname (ndns));
|
|
+ ndctl_unref (ctx);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ndctl_unref (ctx);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
* bd_nvdimm_namespace_enable:
|
|
* @namespace: name of the namespace to enable
|
|
* @extra: (allow-none) (array zero-terminated=1): extra options (currently unused)
|
|
diff --git a/src/plugins/nvdimm.h b/src/plugins/nvdimm.h
|
|
index 5a1642f..fcc1038 100644
|
|
--- a/src/plugins/nvdimm.h
|
|
+++ b/src/plugins/nvdimm.h
|
|
@@ -65,6 +65,8 @@ gboolean bd_nvdimm_is_tech_avail (BDNVDIMMTech tech, guint64 mode, GError **erro
|
|
BDNVDIMMNamespaceMode bd_nvdimm_namespace_get_mode_from_str (const gchar *mode_str, GError **error);
|
|
const gchar* bd_nvdimm_namespace_get_mode_str (BDNVDIMMNamespaceMode mode, GError **error);
|
|
|
|
+gchar* bd_nvdimm_namespace_get_devname (const gchar *device, GError **error);
|
|
+
|
|
gboolean bd_nvdimm_namespace_enable (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
gboolean bd_nvdimm_namespace_disable (const gchar *namespace, const BDExtraArg **extra, GError **error);
|
|
|
|
diff --git a/tests/nvdimm_test.py b/tests/nvdimm_test.py
|
|
index b4eb43d..92a6653 100644
|
|
--- a/tests/nvdimm_test.py
|
|
+++ b/tests/nvdimm_test.py
|
|
@@ -73,6 +73,14 @@ class NVDIMMNamespaceTestCase(NVDIMMTestCase):
|
|
info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
|
|
self._check_namespace_info(info)
|
|
|
|
+ # test also that getting namespace devname from blockdev name works
|
|
+ namespace = BlockDev.nvdimm_namespace_get_devname(info.blockdev)
|
|
+ self.assertEqual(namespace, self.sys_info["dev"])
|
|
+
|
|
+ # should work even with path, e.g. /dev/pmem0
|
|
+ namespace = BlockDev.nvdimm_namespace_get_devname("/dev/" + info.blockdev)
|
|
+ self.assertEqual(namespace, self.sys_info["dev"])
|
|
+
|
|
info = BlockDev.nvdimm_namespace_info("definitely-not-a-namespace")
|
|
self.assertIsNone(info)
|
|
|
|
--
|
|
1.8.3.1
|
|
|