Re: [PATCH v6 01/12] mm/sparsemem: Introduce struct mem_section_usage

2019-05-01 Thread Pavel Tatashin
On 19-04-17 11:39:00, Dan Williams wrote:
> Towards enabling memory hotplug to track partial population of a
> section, introduce 'struct mem_section_usage'.
> 
> A pointer to a 'struct mem_section_usage' instance replaces the existing
> pointer to a 'pageblock_flags' bitmap. Effectively it adds one more
> 'unsigned long' beyond the 'pageblock_flags' (usemap) allocation to
> house a new 'map_active' bitmap.  The new bitmap enables the memory
> hot{plug,remove} implementation to act on incremental sub-divisions of a
> section.
> 
> The primary motivation for this functionality is to support platforms
> that mix "System RAM" and "Persistent Memory" within a single section,
> or multiple PMEM ranges with different mapping lifetimes within a single
> section. The section restriction for hotplug has caused an ongoing saga
> of hacks and bugs for devm_memremap_pages() users.
> 
> Beyond the fixups to teach existing paths how to retrieve the 'usemap'
> from a section, and updates to usemap allocation path, there are no
> expected behavior changes.
> 
> Cc: Michal Hocko 
> Cc: Vlastimil Babka 
> Cc: Logan Gunthorpe 
> Signed-off-by: Dan Williams 
> ---
>  include/linux/mmzone.h |   23 --
>  mm/memory_hotplug.c|   18 ++-
>  mm/page_alloc.c|2 +
>  mm/sparse.c|   81 
> 
>  4 files changed, 71 insertions(+), 53 deletions(-)
> 
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 70394cabaf4e..f0bbd85dc19a 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -1160,6 +1160,19 @@ static inline unsigned long section_nr_to_pfn(unsigned 
> long sec)
>  #define SECTION_ALIGN_UP(pfn)(((pfn) + PAGES_PER_SECTION - 1) & 
> PAGE_SECTION_MASK)
>  #define SECTION_ALIGN_DOWN(pfn)  ((pfn) & PAGE_SECTION_MASK)
>  
> +#define SECTION_ACTIVE_SIZE ((1UL << SECTION_SIZE_BITS) / BITS_PER_LONG)
> +#define SECTION_ACTIVE_MASK (~(SECTION_ACTIVE_SIZE - 1))
> +
> +struct mem_section_usage {
> + /*
> +  * SECTION_ACTIVE_SIZE portions of the section that are populated in
> +  * the memmap
> +  */
> + unsigned long map_active;

I think this should be proportional to section_size / subsection_size.
For example, on intel section size = 128M, and subsection is 2M, so
64bits work nicely. But, on arm64 section size if 1G, so subsection is
16M.

On the other hand 16M is already much better than what we have: with 1G
section size and 2M pmem alignment we guaranteed to loose 1022M. And
with 16M subsection it is only 14M.
___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[PATCH v2 16/17] kernel/sysctl-test: Add null pointer test for sysctl.c:proc_dointvec()

2019-05-01 Thread Brendan Higgins
From: Iurii Zaikin 

KUnit tests for initialized data behavior of proc_dointvec that is
explicitly checked in the code. Includes basic parsing tests including
int min/max overflow.

Signed-off-by: Iurii Zaikin 
Signed-off-by: Brendan Higgins 
---
 kernel/Makefile  |   2 +
 kernel/sysctl-test.c | 292 +++
 lib/Kconfig.debug|   6 +
 3 files changed, 300 insertions(+)
 create mode 100644 kernel/sysctl-test.c

diff --git a/kernel/Makefile b/kernel/Makefile
index 6c57e78817dad..c81a8976b6a4b 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -112,6 +112,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomem.o
 obj-$(CONFIG_ZONE_DEVICE) += memremap.o
 obj-$(CONFIG_RSEQ) += rseq.o
 
+obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o
+
 obj-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak.o
 KASAN_SANITIZE_stackleak.o := n
 KCOV_INSTRUMENT_stackleak.o := n
diff --git a/kernel/sysctl-test.c b/kernel/sysctl-test.c
new file mode 100644
index 0..a0fba6b6fc2dc
--- /dev/null
+++ b/kernel/sysctl-test.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test of proc sysctl.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+static int i_zero;
+static int i_one_hundred = 100;
+
+struct test_sysctl_data {
+   int int_0001;
+   int int_0002;
+   int int_0003[4];
+
+   unsigned int uint_0001;
+
+   char string_0001[65];
+};
+
+static struct test_sysctl_data test_data = {
+   .int_0001 = 60,
+   .int_0002 = 1,
+
+   .int_0003[0] = 0,
+   .int_0003[1] = 1,
+   .int_0003[2] = 2,
+   .int_0003[3] = 3,
+
+   .uint_0001 = 314,
+
+   .string_0001 = "(none)",
+};
+
+static void sysctl_test_dointvec_null_tbl_data(struct kunit *test)
+{
+   struct ctl_table table = {
+   .procname = "foo",
+   .data   = NULL,
+   .maxlen = sizeof(int),
+   .mode   = 0644,
+   .proc_handler   = proc_dointvec,
+   .extra1 = _zero,
+   .extra2 = _one_hundred,
+   };
+   void  *buffer = kunit_kzalloc(test, sizeof(int), GFP_USER);
+   size_t len;
+   loff_t pos;
+
+   len = 1234;
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 0, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+   len = 1234;
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 1, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+}
+
+static void sysctl_test_dointvec_table_maxlen_unset(struct kunit *test)
+{
+   struct ctl_table table = {
+   .procname = "foo",
+   .data   = _data.int_0001,
+   .maxlen = 0,
+   .mode   = 0644,
+   .proc_handler   = proc_dointvec,
+   .extra1 = _zero,
+   .extra2 = _one_hundred,
+   };
+   void  *buffer = kunit_kzalloc(test, sizeof(int), GFP_USER);
+   size_t len;
+   loff_t pos;
+
+   len = 1234;
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 0, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+   len = 1234;
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 1, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+}
+
+static void sysctl_test_dointvec_table_len_is_zero(struct kunit *test)
+{
+   struct ctl_table table = {
+   .procname = "foo",
+   .data   = _data.int_0001,
+   .maxlen = sizeof(int),
+   .mode   = 0644,
+   .proc_handler   = proc_dointvec,
+   .extra1 = _zero,
+   .extra2 = _one_hundred,
+   };
+   void  *buffer = kunit_kzalloc(test, sizeof(int), GFP_USER);
+   size_t len;
+   loff_t pos;
+
+   len = 0;
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 0, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 1, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+}
+
+static void sysctl_test_dointvec_table_read_but_position_set(struct kunit 
*test)
+{
+   struct ctl_table table = {
+   .procname = "foo",
+   .data   = _data.int_0001,
+   .maxlen = sizeof(int),
+   .mode   = 0644,
+   .proc_handler   = proc_dointvec,
+   .extra1 = _zero,
+   .extra2 = _one_hundred,
+   };
+   void  *buffer = kunit_kzalloc(test, sizeof(int), GFP_USER);
+   size_t len;
+   loff_t pos;
+
+   len = 1234;
+   pos = 1;
+   KUNIT_EXPECT_EQ(test, 0, proc_dointvec(, 0, buffer, , ));
+   KUNIT_EXPECT_EQ(test, 0, len);
+}
+
+static void sysctl_test_dointvec_happy_single_positive(struct kunit *test)
+{
+   struct ctl_table table = {
+   .procname = "foo",
+   .data   = _data.int_0001,
+   .maxlen = sizeof(int),
+   .mode   = 

[PATCH v2 17/17] MAINTAINERS: add proc sysctl KUnit test to PROC SYSCTL section

2019-05-01 Thread Brendan Higgins
Add entry for the new proc sysctl KUnit test to the PROC SYSCTL section.

Signed-off-by: Brendan Higgins 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index c78ae95c56b80..23cc97332c3d7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12524,6 +12524,7 @@ S:  Maintained
 F: fs/proc/proc_sysctl.c
 F: include/linux/sysctl.h
 F: kernel/sysctl.c
+F: kernel/sysctl-test.c
 F: tools/testing/selftests/sysctl/
 
 PS3 NETWORK SUPPORT
-- 
2.21.0.593.g511ec345e18-goog

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[PATCH v2 12/17] kunit: tool: add Python wrappers for running KUnit tests

2019-05-01 Thread Brendan Higgins
From: Felix Guo 

The ultimate goal is to create minimal isolated test binaries; in the
meantime we are using UML to provide the infrastructure to run tests, so
define an abstract way to configure and run tests that allow us to
change the context in which tests are built without affecting the user.
This also makes pretty and dynamic error reporting, and a lot of other
nice features easier.

kunit_config.py:
  - parse .config and Kconfig files.

kunit_kernel.py: provides helper functions to:
  - configure the kernel using kunitconfig.
  - build the kernel with the appropriate configuration.
  - provide function to invoke the kernel and stream the output back.

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 tools/testing/kunit/.gitignore  |   3 +
 tools/testing/kunit/kunit.py|  78 +++
 tools/testing/kunit/kunit_config.py |  66 +
 tools/testing/kunit/kunit_kernel.py | 148 
 tools/testing/kunit/kunit_parser.py | 119 ++
 5 files changed, 414 insertions(+)
 create mode 100644 tools/testing/kunit/.gitignore
 create mode 100755 tools/testing/kunit/kunit.py
 create mode 100644 tools/testing/kunit/kunit_config.py
 create mode 100644 tools/testing/kunit/kunit_kernel.py
 create mode 100644 tools/testing/kunit/kunit_parser.py

diff --git a/tools/testing/kunit/.gitignore b/tools/testing/kunit/.gitignore
new file mode 100644
index 0..c791ff59a37a9
--- /dev/null
+++ b/tools/testing/kunit/.gitignore
@@ -0,0 +1,3 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
\ No newline at end of file
diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
new file mode 100755
index 0..7413ec7351a20
--- /dev/null
+++ b/tools/testing/kunit/kunit.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# A thin wrapper on top of the KUnit Kernel
+#
+# Copyright (C) 2019, Google LLC.
+# Author: Felix Guo 
+# Author: Brendan Higgins 
+
+import argparse
+import sys
+import os
+import time
+
+import kunit_config
+import kunit_kernel
+import kunit_parser
+
+parser = argparse.ArgumentParser(description='Runs KUnit tests.')
+
+parser.add_argument('--raw_output', help='don\'t format output from kernel',
+   action='store_true')
+
+parser.add_argument('--timeout', help='maximum number of seconds to allow for '
+   'all tests to run. This does not include time taken to '
+   'build the tests.', type=int, default=300,
+   metavar='timeout')
+
+parser.add_argument('--jobs',
+   help='As in the make command, "Specifies  the number of '
+   'jobs (commands) to run simultaneously."',
+   type=int, default=8, metavar='jobs')
+
+parser.add_argument('--build_dir',
+   help='As in the make command, it specifies the build '
+   'directory.',
+   type=str, default=None, metavar='build_dir')
+
+cli_args = parser.parse_args()
+
+linux = kunit_kernel.LinuxSourceTree()
+
+build_dir = None
+if cli_args.build_dir:
+   build_dir = cli_args.build_dir
+
+config_start = time.time()
+success = linux.build_reconfig(build_dir)
+config_end = time.time()
+if not success:
+   quit()
+
+kunit_parser.print_with_timestamp('Building KUnit Kernel ...')
+
+build_start = time.time()
+
+success = linux.build_um_kernel(jobs=cli_args.jobs, build_dir=build_dir)
+build_end = time.time()
+if not success:
+   quit()
+
+kunit_parser.print_with_timestamp('Starting KUnit Kernel ...')
+test_start = time.time()
+
+if cli_args.raw_output:
+   kunit_parser.raw_output(linux.run_kernel(timeout=cli_args.timeout,
+build_dir=build_dir))
+else:
+   kunit_parser.parse_run_tests(linux.run_kernel(timeout=cli_args.timeout,
+ build_dir=build_dir))
+
+test_end = time.time()
+
+kunit_parser.print_with_timestamp((
+   "Elapsed time: %.3fs total, %.3fs configuring, %.3fs " +
+   "building, %.3fs running.\n") % (test_end - config_start,
+   config_end - config_start, build_end - build_start,
+   test_end - test_start))
diff --git a/tools/testing/kunit/kunit_config.py 
b/tools/testing/kunit/kunit_config.py
new file mode 100644
index 0..167f47d9ab8e4
--- /dev/null
+++ b/tools/testing/kunit/kunit_config.py
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Builds a .config from a kunitconfig.
+#
+# Copyright (C) 2019, Google LLC.
+# Author: Felix Guo 
+# Author: Brendan Higgins 
+
+import collections
+import re
+
+CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_\w+ is not set$'
+CONFIG_PATTERN = r'^CONFIG_\w+=\S+$'
+
+KconfigEntryBase = collections.namedtuple('KconfigEntry', ['raw_entry'])
+
+
+class KconfigEntry(KconfigEntryBase):
+
+   def __str__(self) -> str:
+   return self.raw_entry
+
+
+class 

[PATCH v2 15/17] MAINTAINERS: add entry for KUnit the unit testing framework

2019-05-01 Thread Brendan Higgins
Add myself as maintainer of KUnit, the Linux kernel's unit testing
framework.

Signed-off-by: Brendan Higgins 
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5c38f21aee787..c78ae95c56b80 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8448,6 +8448,16 @@ S:   Maintained
 F: tools/testing/selftests/
 F: Documentation/dev-tools/kselftest*
 
+KERNEL UNIT TESTING FRAMEWORK (KUnit)
+M: Brendan Higgins 
+L: kunit-...@googlegroups.com
+W: https://google.github.io/kunit-docs/third_party/kernel/docs/
+S: Maintained
+F: Documentation/kunit/
+F: include/kunit/
+F: kunit/
+F: tools/testing/kunit/
+
 KERNEL USERMODE HELPER
 M: Luis Chamberlain 
 L: linux-ker...@vger.kernel.org
-- 
2.21.0.593.g511ec345e18-goog

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[PATCH v2 14/17] Documentation: kunit: add documentation for KUnit

2019-05-01 Thread Brendan Higgins
Add documentation for KUnit, the Linux kernel unit testing framework.
- Add intro and usage guide for KUnit
- Add API reference

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 Documentation/index.rst   |   1 +
 Documentation/kunit/api/index.rst |  16 ++
 Documentation/kunit/api/test.rst  |  15 +
 Documentation/kunit/faq.rst   |  46 +++
 Documentation/kunit/index.rst |  80 ++
 Documentation/kunit/start.rst | 180 
 Documentation/kunit/usage.rst | 447 ++
 7 files changed, 785 insertions(+)
 create mode 100644 Documentation/kunit/api/index.rst
 create mode 100644 Documentation/kunit/api/test.rst
 create mode 100644 Documentation/kunit/faq.rst
 create mode 100644 Documentation/kunit/index.rst
 create mode 100644 Documentation/kunit/start.rst
 create mode 100644 Documentation/kunit/usage.rst

diff --git a/Documentation/index.rst b/Documentation/index.rst
index 80a421cb935e7..264cfd613a774 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -65,6 +65,7 @@ merged much easier.
kernel-hacking/index
trace/index
maintainer/index
+   kunit/index
 
 Kernel API documentation
 
diff --git a/Documentation/kunit/api/index.rst 
b/Documentation/kunit/api/index.rst
new file mode 100644
index 0..c31c530088153
--- /dev/null
+++ b/Documentation/kunit/api/index.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=
+API Reference
+=
+.. toctree::
+
+   test
+
+This section documents the KUnit kernel testing API. It is divided into 3
+sections:
+
+= 
==
+:doc:`test`   documents all of the standard testing API
+  excluding mocking or mocking related 
features.
+= 
==
diff --git a/Documentation/kunit/api/test.rst b/Documentation/kunit/api/test.rst
new file mode 100644
index 0..7c926014f047c
--- /dev/null
+++ b/Documentation/kunit/api/test.rst
@@ -0,0 +1,15 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+Test API
+
+
+This file documents all of the standard testing API excluding mocking or 
mocking
+related features.
+
+.. kernel-doc:: include/kunit/test.h
+   :internal:
+
+.. kernel-doc:: include/kunit/kunit-stream.h
+   :internal:
+
diff --git a/Documentation/kunit/faq.rst b/Documentation/kunit/faq.rst
new file mode 100644
index 0..cb8e4fb2257a0
--- /dev/null
+++ b/Documentation/kunit/faq.rst
@@ -0,0 +1,46 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=
+Frequently Asked Questions
+=
+
+How is this different from Autotest, kselftest, etc?
+
+KUnit is a unit testing framework. Autotest, kselftest (and some others) are
+not.
+
+A `unit test `_ is supposed to
+test a single unit of code in isolation, hence the name. A unit test should be
+the finest granularity of testing and as such should allow all possible code
+paths to be tested in the code under test; this is only possible if the code
+under test is very small and does not have any external dependencies outside of
+the test's control like hardware.
+
+There are no testing frameworks currently available for the kernel that do not
+require installing the kernel on a test machine or in a VM and all require
+tests to be written in userspace and run on the kernel under test; this is true
+for Autotest, kselftest, and some others, disqualifying any of them from being
+considered unit testing frameworks.
+
+What is the difference between a unit test and these other kinds of tests?
+==
+Most existing tests for the Linux kernel would be categorized as an integration
+test, or an end-to-end test.
+
+- A unit test is supposed to test a single unit of code in isolation, hence the
+  name. A unit test should be the finest granularity of testing and as such
+  should allow all possible code paths to be tested in the code under test; 
this
+  is only possible if the code under test is very small and does not have any
+  external dependencies outside of the test's control like hardware.
+- An integration test tests the interaction between a minimal set of 
components,
+  usually just two or three. For example, someone might write an integration
+  test to test the interaction between a driver and a piece of hardware, or to
+  test the interaction between the userspace libraries the kernel provides and
+  the kernel itself; however, one of these tests would probably not test the
+  entire kernel along with hardware interactions and interactions with the
+  userspace.
+- An end-to-end test usually tests the entire system from the 

[PATCH v2 13/17] kunit: defconfig: add defconfigs for building KUnit tests

2019-05-01 Thread Brendan Higgins
Add defconfig for UML and a fragment that can be used to configure other
architectures for building KUnit tests. Add option to kunit_tool to use
a defconfig to create the kunitconfig.

Signed-off-by: Brendan Higgins 
---
 arch/um/configs/kunit_defconfig  |  8 
 tools/testing/kunit/configs/all_tests.config |  8 
 tools/testing/kunit/kunit.py | 17 +++--
 tools/testing/kunit/kunit_kernel.py  |  3 ++-
 4 files changed, 33 insertions(+), 3 deletions(-)
 create mode 100644 arch/um/configs/kunit_defconfig
 create mode 100644 tools/testing/kunit/configs/all_tests.config

diff --git a/arch/um/configs/kunit_defconfig b/arch/um/configs/kunit_defconfig
new file mode 100644
index 0..bfe49689038f1
--- /dev/null
+++ b/arch/um/configs/kunit_defconfig
@@ -0,0 +1,8 @@
+CONFIG_OF=y
+CONFIG_OF_UNITTEST=y
+CONFIG_OF_OVERLAY=y
+CONFIG_I2C=y
+CONFIG_I2C_MUX=y
+CONFIG_KUNIT=y
+CONFIG_KUNIT_TEST=y
+CONFIG_KUNIT_EXAMPLE_TEST=y
diff --git a/tools/testing/kunit/configs/all_tests.config 
b/tools/testing/kunit/configs/all_tests.config
new file mode 100644
index 0..bfe49689038f1
--- /dev/null
+++ b/tools/testing/kunit/configs/all_tests.config
@@ -0,0 +1,8 @@
+CONFIG_OF=y
+CONFIG_OF_UNITTEST=y
+CONFIG_OF_OVERLAY=y
+CONFIG_I2C=y
+CONFIG_I2C_MUX=y
+CONFIG_KUNIT=y
+CONFIG_KUNIT_TEST=y
+CONFIG_KUNIT_EXAMPLE_TEST=y
diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 7413ec7351a20..63e9fb3b60200 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -11,6 +11,7 @@ import argparse
 import sys
 import os
 import time
+import shutil
 
 import kunit_config
 import kunit_kernel
@@ -36,14 +37,26 @@ parser.add_argument('--build_dir',
'directory.',
type=str, default=None, metavar='build_dir')
 
-cli_args = parser.parse_args()
+parser.add_argument('--defconfig',
+   help='Uses a default kunitconfig.',
+   action='store_true')
 
-linux = kunit_kernel.LinuxSourceTree()
+def create_default_kunitconfig():
+   if not os.path.exists(kunit_kernel.KUNITCONFIG_PATH):
+   shutil.copyfile('arch/um/configs/kunit_defconfig',
+   kunit_kernel.KUNITCONFIG_PATH)
+
+cli_args = parser.parse_args()
 
 build_dir = None
 if cli_args.build_dir:
build_dir = cli_args.build_dir
 
+if cli_args.defconfig:
+   create_default_kunitconfig()
+
+linux = kunit_kernel.LinuxSourceTree()
+
 config_start = time.time()
 success = linux.build_reconfig(build_dir)
 config_end = time.time()
diff --git a/tools/testing/kunit/kunit_kernel.py 
b/tools/testing/kunit/kunit_kernel.py
index 07c0abf2f47df..bf38768353313 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -14,6 +14,7 @@ import os
 import kunit_config
 
 KCONFIG_PATH = '.config'
+KUNITCONFIG_PATH = 'kunitconfig'
 
 class ConfigError(Exception):
"""Represents an error trying to configure the Linux kernel."""
@@ -81,7 +82,7 @@ class LinuxSourceTree(object):
 
def __init__(self):
self._kconfig = kunit_config.Kconfig()
-   self._kconfig.read_from_file('kunitconfig')
+   self._kconfig.read_from_file(KUNITCONFIG_PATH)
self._ops = LinuxSourceTreeOperations()
 
def clean(self):
-- 
2.21.0.593.g511ec345e18-goog

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[PATCH v2 09/17] kunit: test: add tests for kunit test abort

2019-05-01 Thread Brendan Higgins
Add KUnit tests for the KUnit test abort mechanism (see preceding
commit). Add tests both for general try catch mechanism as well as
non-architecture specific mechanism.

Signed-off-by: Brendan Higgins 
---
 kunit/Makefile|   3 +-
 kunit/test-test.c | 135 ++
 2 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 kunit/test-test.c

diff --git a/kunit/Makefile b/kunit/Makefile
index 1f7680cfa11ad..533355867abd2 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_KUNIT) +=  test.o \
kunit-stream.o \
try-catch.o
 
-obj-$(CONFIG_KUNIT_TEST) +=string-stream-test.o
+obj-$(CONFIG_KUNIT_TEST) +=test-test.o \
+   string-stream-test.o
 
 obj-$(CONFIG_KUNIT_EXAMPLE_TEST) +=example-test.o
diff --git a/kunit/test-test.c b/kunit/test-test.c
new file mode 100644
index 0..c81ae6efb959f
--- /dev/null
+++ b/kunit/test-test.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for core test infrastructure.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+#include 
+
+struct kunit_try_catch_test_context {
+   struct kunit_try_catch *try_catch;
+   bool function_called;
+};
+
+void kunit_test_successful_try(void *data)
+{
+   struct kunit *test = data;
+   struct kunit_try_catch_test_context *ctx = test->priv;
+
+   ctx->function_called = true;
+}
+
+void kunit_test_no_catch(void *data)
+{
+   struct kunit *test = data;
+
+   KUNIT_FAIL(test, "Catch should not be called.\n");
+}
+
+static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
+{
+   struct kunit_try_catch_test_context *ctx = test->priv;
+   struct kunit_try_catch *try_catch = ctx->try_catch;
+
+   kunit_try_catch_init(try_catch,
+test,
+kunit_test_successful_try,
+kunit_test_no_catch);
+   kunit_try_catch_run(try_catch, test);
+
+   KUNIT_EXPECT_TRUE(test, ctx->function_called);
+}
+
+void kunit_test_unsuccessful_try(void *data)
+{
+   struct kunit *test = data;
+   struct kunit_try_catch_test_context *ctx = test->priv;
+   struct kunit_try_catch *try_catch = ctx->try_catch;
+
+   kunit_try_catch_throw(try_catch);
+   KUNIT_FAIL(test, "This line should never be reached.\n");
+}
+
+void kunit_test_catch(void *data)
+{
+   struct kunit *test = data;
+   struct kunit_try_catch_test_context *ctx = test->priv;
+
+   ctx->function_called = true;
+}
+
+static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit 
*test)
+{
+   struct kunit_try_catch_test_context *ctx = test->priv;
+   struct kunit_try_catch *try_catch = ctx->try_catch;
+
+   kunit_try_catch_init(try_catch,
+test,
+kunit_test_unsuccessful_try,
+kunit_test_catch);
+   kunit_try_catch_run(try_catch, test);
+
+   KUNIT_EXPECT_TRUE(test, ctx->function_called);
+}
+
+static void kunit_test_generic_try_catch_successful_try_no_catch(
+   struct kunit *test)
+{
+   struct kunit_try_catch_test_context *ctx = test->priv;
+   struct kunit_try_catch *try_catch = ctx->try_catch;
+
+   try_catch->test = test;
+   kunit_generic_try_catch_init(try_catch);
+   try_catch->try = kunit_test_successful_try;
+   try_catch->catch = kunit_test_no_catch;
+
+   kunit_try_catch_run(try_catch, test);
+
+   KUNIT_EXPECT_TRUE(test, ctx->function_called);
+}
+
+static void kunit_test_generic_try_catch_unsuccessful_try_does_catch(
+   struct kunit *test)
+{
+   struct kunit_try_catch_test_context *ctx = test->priv;
+   struct kunit_try_catch *try_catch = ctx->try_catch;
+
+   try_catch->test = test;
+   kunit_generic_try_catch_init(try_catch);
+   try_catch->try = kunit_test_unsuccessful_try;
+   try_catch->catch = kunit_test_catch;
+
+   kunit_try_catch_run(try_catch, test);
+
+   KUNIT_EXPECT_TRUE(test, ctx->function_called);
+}
+
+static int kunit_try_catch_test_init(struct kunit *test)
+{
+   struct kunit_try_catch_test_context *ctx;
+
+   ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+   test->priv = ctx;
+
+   ctx->try_catch = kunit_kmalloc(test,
+  sizeof(*ctx->try_catch),
+  GFP_KERNEL);
+
+   return 0;
+}
+
+static struct kunit_case kunit_try_catch_test_cases[] = {
+   KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
+   KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
+   KUNIT_CASE(kunit_test_generic_try_catch_successful_try_no_catch),
+   

[PATCH v2 11/17] kunit: test: add test managed resource tests

2019-05-01 Thread Brendan Higgins
From: Avinash Kondareddy 

Tests how tests interact with test managed resources in their lifetime.

Signed-off-by: Avinash Kondareddy 
Signed-off-by: Brendan Higgins 
---
 kunit/test-test.c | 122 ++
 1 file changed, 122 insertions(+)

diff --git a/kunit/test-test.c b/kunit/test-test.c
index 4bd7a34d0a6cb..54add8ca418a0 100644
--- a/kunit/test-test.c
+++ b/kunit/test-test.c
@@ -135,3 +135,125 @@ static struct kunit_module kunit_try_catch_test_module = {
.test_cases = kunit_try_catch_test_cases,
 };
 module_test(kunit_try_catch_test_module);
+
+/*
+ * Context for testing test managed resources
+ * is_resource_initialized is used to test arbitrary resources
+ */
+struct kunit_test_resource_context {
+   struct kunit test;
+   bool is_resource_initialized;
+};
+
+static int fake_resource_init(struct kunit_resource *res, void *context)
+{
+   struct kunit_test_resource_context *ctx = context;
+
+   res->allocation = >is_resource_initialized;
+   ctx->is_resource_initialized = true;
+   return 0;
+}
+
+static void fake_resource_free(struct kunit_resource *res)
+{
+   bool *is_resource_initialized = res->allocation;
+
+   *is_resource_initialized = false;
+}
+
+static void kunit_resource_test_init_resources(struct kunit *test)
+{
+   struct kunit_test_resource_context *ctx = test->priv;
+
+   kunit_init_test(>test, "testing_test_init_test");
+
+   KUNIT_EXPECT_TRUE(test, list_empty(>test.resources));
+}
+
+static void kunit_resource_test_alloc_resource(struct kunit *test)
+{
+   struct kunit_test_resource_context *ctx = test->priv;
+   struct kunit_resource *res;
+   kunit_resource_free_t free = fake_resource_free;
+
+   res = kunit_alloc_resource(>test,
+  fake_resource_init,
+  fake_resource_free,
+  ctx);
+
+   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
+   KUNIT_EXPECT_EQ(test, >is_resource_initialized, res->allocation);
+   KUNIT_EXPECT_TRUE(test, list_is_last(>node, >test.resources));
+   KUNIT_EXPECT_EQ(test, free, res->free);
+}
+
+static void kunit_resource_test_free_resource(struct kunit *test)
+{
+   struct kunit_test_resource_context *ctx = test->priv;
+   struct kunit_resource *res = kunit_alloc_resource(>test,
+ fake_resource_init,
+ fake_resource_free,
+ ctx);
+
+   kunit_free_resource(>test, res);
+
+   KUNIT_EXPECT_EQ(test, false, ctx->is_resource_initialized);
+   KUNIT_EXPECT_TRUE(test, list_empty(>test.resources));
+}
+
+static void kunit_resource_test_cleanup_resources(struct kunit *test)
+{
+   int i;
+   struct kunit_test_resource_context *ctx = test->priv;
+   struct kunit_resource *resources[5];
+
+   for (i = 0; i < ARRAY_SIZE(resources); i++) {
+   resources[i] = kunit_alloc_resource(>test,
+   fake_resource_init,
+   fake_resource_free,
+   ctx);
+   }
+
+   kunit_cleanup(>test);
+
+   KUNIT_EXPECT_TRUE(test, list_empty(>test.resources));
+}
+
+static int kunit_resource_test_init(struct kunit *test)
+{
+   struct kunit_test_resource_context *ctx =
+   kzalloc(sizeof(*ctx), GFP_KERNEL);
+
+   if (!ctx)
+   return -ENOMEM;
+
+   test->priv = ctx;
+
+   kunit_init_test(>test, "test_test_context");
+
+   return 0;
+}
+
+static void kunit_resource_test_exit(struct kunit *test)
+{
+   struct kunit_test_resource_context *ctx = test->priv;
+
+   kunit_cleanup(>test);
+   kfree(ctx);
+}
+
+static struct kunit_case kunit_resource_test_cases[] = {
+   KUNIT_CASE(kunit_resource_test_init_resources),
+   KUNIT_CASE(kunit_resource_test_alloc_resource),
+   KUNIT_CASE(kunit_resource_test_free_resource),
+   KUNIT_CASE(kunit_resource_test_cleanup_resources),
+   {},
+};
+
+static struct kunit_module kunit_resource_test_module = {
+   .name = "kunit-resource-test",
+   .init = kunit_resource_test_init,
+   .exit = kunit_resource_test_exit,
+   .test_cases = kunit_resource_test_cases,
+};
+module_test(kunit_resource_test_module);
-- 
2.21.0.593.g511ec345e18-goog

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[PATCH v2 05/17] kunit: test: add the concept of expectations

2019-05-01 Thread Brendan Higgins
Add support for expectations, which allow properties to be specified and
then verified in tests.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 419 +++
 kunit/test.c |  34 
 2 files changed, 453 insertions(+)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 4668e8a635954..e441270561ece 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -273,4 +273,423 @@ void __printf(3, 4) kunit_printk(const char *level,
 #define kunit_err(test, fmt, ...) \
kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
 
+static inline struct kunit_stream *kunit_expect_start(struct kunit *test,
+ const char *file,
+ const char *line)
+{
+   struct kunit_stream *stream = kunit_new_stream(test);
+
+   kunit_stream_add(stream, "EXPECTATION FAILED at %s:%s\n\t", file, line);
+
+   return stream;
+}
+
+static inline void kunit_expect_end(struct kunit *test,
+   bool success,
+   struct kunit_stream *stream)
+{
+   if (!success)
+   test->fail(test, stream);
+   else
+   kunit_stream_clear(stream);
+}
+
+#define KUNIT_EXPECT_START(test) \
+   kunit_expect_start(test, __FILE__, __stringify(__LINE__))
+
+#define KUNIT_EXPECT_END(test, success, stream) \
+   kunit_expect_end(test, success, stream)
+
+#define KUNIT_EXPECT_MSG(test, success, message, fmt, ...) do {
   \
+   struct kunit_stream *__stream = KUNIT_EXPECT_START(test);  \
+  \
+   kunit_stream_add(__stream, message);   \
+   kunit_stream_add(__stream, fmt, ##__VA_ARGS__);\
+   KUNIT_EXPECT_END(test, success, __stream); \
+} while (0)
+
+#define KUNIT_EXPECT(test, success, message) do { \
+   struct kunit_stream *__stream = KUNIT_EXPECT_START(test);  \
+  \
+   kunit_stream_add(__stream, message);   \
+   KUNIT_EXPECT_END(test, success, __stream); \
+} while (0)
+
+/**
+ * KUNIT_SUCCEED() - A no-op expectation. Only exists for code clarity.
+ * @test: The test context object.
+ *
+ * The opposite of KUNIT_FAIL(), it is an expectation that cannot fail. In 
other
+ * words, it does nothing and only exists for code clarity. See
+ * KUNIT_EXPECT_TRUE() for more information.
+ */
+#define KUNIT_SUCCEED(test) do {} while (0)
+
+/**
+ * KUNIT_FAIL() - Always causes a test to fail when evaluated.
+ * @test: The test context object.
+ * @fmt: an informational message to be printed when the assertion is made.
+ * @...: string format arguments.
+ *
+ * The opposite of KUNIT_SUCCEED(), it is an expectation that always fails. In
+ * other words, it always results in a failed expectation, and consequently
+ * always causes the test case to fail when evaluated. See KUNIT_EXPECT_TRUE()
+ * for more information.
+ */
+#define KUNIT_FAIL(test, fmt, ...) do {
   \
+   struct kunit_stream *__stream = KUNIT_EXPECT_START(test);  \
+  \
+   kunit_stream_add(__stream, fmt, ##__VA_ARGS__);\
+   KUNIT_EXPECT_END(test, false, __stream);   \
+} while (0)
+
+/**
+ * KUNIT_EXPECT_TRUE() - Causes a test failure when the expression is not true.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails when this does
+ * not evaluate to true.
+ *
+ * This and expectations of the form `KUNIT_EXPECT_*` will cause the test case
+ * to fail when the specified condition is not met; however, it will not 
prevent
+ * the test case from continuing to run; this is otherwise known as an
+ * *expectation failure*.
+ */
+#define KUNIT_EXPECT_TRUE(test, condition)\
+   KUNIT_EXPECT(test, (condition),\
+  "Expected " #condition " is true, but is false.\n")
+
+#define KUNIT_EXPECT_TRUE_MSG(test, condition, fmt, ...)  \
+   KUNIT_EXPECT_MSG(test, (condition),\
+   "Expected " #condition " is true, but is 
false.\n",\
+   fmt, ##__VA_ARGS__)
+
+/**
+ * KUNIT_EXPECT_FALSE() - Makes a test failure when the expression is not 
false.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails when this does
+ * not evaluate 

[PATCH v2 10/17] kunit: test: add the concept of assertions

2019-05-01 Thread Brendan Higgins
Add support for assertions which are like expectations except the test
terminates if the assertion is not satisfied.

The idea with assertions is that you use them to state all the
preconditions for your test. Logically speaking, these are the premises
of the test case, so if a premise isn't true, there is no point in
continuing the test case because there are no conclusions that can be
drawn without the premises. Whereas, the expectation is the thing you
are trying to prove. It is not used universally in x-unit style test
frameworks, but I really like it as a convention.  You could still
express the idea of a premise using the above idiom, but I think
KUNIT_ASSERT_* states the intended idea perfectly.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h   | 401 -
 kunit/string-stream-test.c |  12 +-
 kunit/test-test.c  |   2 +
 kunit/test.c   |  33 +++
 4 files changed, 439 insertions(+), 9 deletions(-)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 1b77caeb5d51f..bb2f3e63a3522 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -85,9 +85,10 @@ struct kunit;
  * @name: the name of the test case.
  *
  * A test case is a function with the signature, ``void (*)(struct kunit *)``
- * that makes expectations (see KUNIT_EXPECT_TRUE()) about code under test. 
Each
- * test case is associated with a  kunit_module and will be run after 
the
- * module's init function and followed by the module's exit function.
+ * that makes expectations and assertions (see KUNIT_EXPECT_TRUE() and
+ * KUNIT_ASSERT_TRUE()) about code under test. Each test case is associated 
with
+ * a  kunit_module and will be run after the module's init function and
+ * followed by the module's exit function.
  *
  * A test case should be static and should only be created with the 
KUNIT_CASE()
  * macro; additionally, every array of test cases should be terminated with an
@@ -705,4 +706,398 @@ static inline void kunit_expect_binary(struct kunit *test,
KUNIT_EXPECT_END(test, !IS_ERR_OR_NULL(__ptr), __stream);  \
 } while (0)
 
+static inline struct kunit_stream *kunit_assert_start(struct kunit *test,
+ const char *file,
+ const char *line)
+{
+   struct kunit_stream *stream = kunit_new_stream(test);
+
+   kunit_stream_add(stream, "ASSERTION FAILED at %s:%s\n\t", file, line);
+
+   return stream;
+}
+
+static inline void kunit_assert_end(struct kunit *test,
+   bool success,
+   struct kunit_stream *stream)
+{
+   if (!success) {
+   test->fail(test, stream);
+   test->abort(test);
+   } else {
+   kunit_stream_clear(stream);
+   }
+}
+
+#define KUNIT_ASSERT_START(test) \
+   kunit_assert_start(test, __FILE__, __stringify(__LINE__))
+
+#define KUNIT_ASSERT_END(test, success, stream) \
+   kunit_assert_end(test, success, stream)
+
+#define KUNIT_ASSERT(test, success, message) do { \
+   struct kunit_stream *__stream = KUNIT_ASSERT_START(test);  \
+  \
+   kunit_stream_add(__stream, message);   \
+   KUNIT_ASSERT_END(test, success, __stream); \
+} while (0)
+
+#define KUNIT_ASSERT_MSG(test, success, message, fmt, ...) do {
   \
+   struct kunit_stream *__stream = KUNIT_ASSERT_START(test);  \
+  \
+   kunit_stream_add(__stream, message);   \
+   kunit_stream_add(__stream, fmt, ##__VA_ARGS__);\
+   KUNIT_ASSERT_END(test, success, __stream); \
+} while (0)
+
+#define KUNIT_ASSERT_FAILURE(test, fmt, ...) do { \
+   struct kunit_stream *__stream = KUNIT_ASSERT_START(test);  \
+  \
+   kunit_stream_add(__stream, fmt, ##__VA_ARGS__);\
+   KUNIT_ASSERT_END(test, false, __stream);   \
+} while (0)
+
+/**
+ * KUNIT_ASSERT_TRUE() - Sets an assertion that @condition is true.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails and aborts when
+ * this does not evaluate to true.
+ *
+ * This and assertions of the form `KUNIT_ASSERT_*` will cause the test case to
+ * fail *and immediately abort* when the specified condition is not met. Unlike
+ * an expectation failure, it will prevent the test case from continuing to 
run;
+ * this is otherwise known as an *assertion failure*.
+ */

[PATCH v2 06/17] kbuild: enable building KUnit

2019-05-01 Thread Brendan Higgins
Add KUnit to root Kconfig and Makefile allowing it to actually be built.

Signed-off-by: Brendan Higgins 
---
 Kconfig  | 2 ++
 Makefile | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/Kconfig b/Kconfig
index 48a80beab6853..10428501edb78 100644
--- a/Kconfig
+++ b/Kconfig
@@ -30,3 +30,5 @@ source "crypto/Kconfig"
 source "lib/Kconfig"
 
 source "lib/Kconfig.debug"
+
+source "kunit/Kconfig"
diff --git a/Makefile b/Makefile
index 2b99679148dc7..77368f498d84c 100644
--- a/Makefile
+++ b/Makefile
@@ -969,7 +969,7 @@ endif
 PHONY += prepare0
 
 ifeq ($(KBUILD_EXTMOD),)
-core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ kunit/
 
 vmlinux-dirs   := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
-- 
2.21.0.593.g511ec345e18-goog

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[PATCH v2 08/17] kunit: test: add support for test abort

2019-05-01 Thread Brendan Higgins
Add support for aborting/bailing out of test cases, which is needed for
implementing assertions.

An assertion is like an expectation, but bails out of the test case
early if the assertion is not met. The idea with assertions is that you
use them to state all the preconditions for your test. Logically
speaking, these are the premises of the test case, so if a premise isn't
true, there is no point in continuing the test case because there are no
conclusions that can be drawn without the premises. Whereas, the
expectation is the thing you are trying to prove.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h  |  13 
 include/kunit/try-catch.h |  91 +
 kunit/Makefile|   3 +-
 kunit/test.c  | 138 +++---
 kunit/try-catch.c |  96 ++
 5 files changed, 332 insertions(+), 9 deletions(-)
 create mode 100644 include/kunit/try-catch.h
 create mode 100644 kunit/try-catch.c

diff --git a/include/kunit/test.h b/include/kunit/test.h
index e441270561ece..1b77caeb5d51f 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct kunit_resource;
 
@@ -166,15 +167,27 @@ struct kunit {
 
/* private: internal use only. */
const char *name; /* Read only after initialization! */
+   struct kunit_try_catch try_catch;
spinlock_t lock; /* Gaurds all mutable test state. */
bool success; /* Protected by lock. */
+   bool death_test; /* Protected by lock. */
struct list_head resources; /* Protected by lock. */
void (*vprintk)(const struct kunit *test,
const char *level,
struct va_format *vaf);
void (*fail)(struct kunit *test, struct kunit_stream *stream);
+   void (*abort)(struct kunit *test);
 };
 
+static inline void kunit_set_death_test(struct kunit *test, bool death_test)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+   test->death_test = death_test;
+   spin_unlock_irqrestore(>lock, flags);
+}
+
 int kunit_init_test(struct kunit *test, const char *name);
 
 int kunit_run_tests(struct kunit_module *module);
diff --git a/include/kunit/try-catch.h b/include/kunit/try-catch.h
new file mode 100644
index 0..e85abe044b6b5
--- /dev/null
+++ b/include/kunit/try-catch.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * An API to allow a function, that may fail, to be executed, and recover in a
+ * controlled manner.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_TRY_CATCH_H
+#define _KUNIT_TRY_CATCH_H
+
+#include 
+
+typedef void (*kunit_try_catch_func_t)(void *);
+
+struct kunit;
+
+/*
+ * struct kunit_try_catch - provides a generic way to run code which might 
fail.
+ * @context: used to pass user data to the try and catch functions.
+ *
+ * kunit_try_catch provides a generic, architecture independent way to execute
+ * an arbitrary function of type kunit_try_catch_func_t which may bail out by
+ * calling kunit_try_catch_throw(). If kunit_try_catch_throw() is called, @try
+ * is stopped at the site of invocation and @catch is catch is called.
+ *
+ * struct kunit_try_catch provides a generic interface for the functionality
+ * needed to implement kunit->abort() which in turn is needed for implementing
+ * assertions. Assertions allow stating a precondition for a test simplifying
+ * how test cases are written and presented.
+ *
+ * Assertions are like expectations, except they abort (call
+ * kunit_try_catch_throw()) when the specified condition is not met. This is
+ * useful when you look at a test case as a logical statement about some piece
+ * of code, where assertions are the premises for the test case, and the
+ * conclusion is a set of predicates, rather expectations, that must all be
+ * true. If your premises are violated, it does not makes sense to continue.
+ */
+struct kunit_try_catch {
+   /* private: internal use only. */
+   void (*run)(struct kunit_try_catch *try_catch);
+   void __noreturn (*throw)(struct kunit_try_catch *try_catch);
+   struct kunit *test;
+   struct completion *try_completion;
+   int try_result;
+   kunit_try_catch_func_t try;
+   kunit_try_catch_func_t catch;
+   void *context;
+};
+
+/*
+ * Exposed to be overridden for other architectures.
+ */
+void kunit_try_catch_init_internal(struct kunit_try_catch *try_catch);
+
+static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
+   struct kunit *test,
+   kunit_try_catch_func_t try,
+   kunit_try_catch_func_t catch)
+{
+   try_catch->test = test;
+   kunit_try_catch_init_internal(try_catch);
+   try_catch->try = try;
+   try_catch->catch = catch;
+}
+
+static 

[PATCH v2 04/17] kunit: test: add kunit_stream a std::stream like logger

2019-05-01 Thread Brendan Higgins
A lot of the expectation and assertion infrastructure prints out fairly
complicated test failure messages, so add a C++ style log library for
for logging test results.

Signed-off-by: Brendan Higgins 
---
 include/kunit/kunit-stream.h |  85 
 include/kunit/test.h |   2 +
 kunit/Makefile   |   3 +-
 kunit/kunit-stream.c | 149 +++
 kunit/test.c |   8 ++
 5 files changed, 246 insertions(+), 1 deletion(-)
 create mode 100644 include/kunit/kunit-stream.h
 create mode 100644 kunit/kunit-stream.c

diff --git a/include/kunit/kunit-stream.h b/include/kunit/kunit-stream.h
new file mode 100644
index 0..d457a54fe0100
--- /dev/null
+++ b/include/kunit/kunit-stream.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * C++ stream style string formatter and printer used in KUnit for outputting
+ * KUnit messages.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_KUNIT_STREAM_H
+#define _KUNIT_KUNIT_STREAM_H
+
+#include 
+#include 
+
+struct kunit;
+
+/**
+ * struct kunit_stream - a std::stream style string builder.
+ *
+ * A std::stream style string builder. Allows messages to be built up and
+ * printed all at once.
+ */
+struct kunit_stream {
+   /* private: internal use only. */
+   struct kunit *test;
+   spinlock_t lock; /* Guards level. */
+   const char *level;
+   struct string_stream *internal_stream;
+};
+
+/**
+ * kunit_new_stream() - constructs a new  kunit_stream.
+ * @test: The test context object.
+ *
+ * Constructs a new test managed  kunit_stream.
+ */
+struct kunit_stream *kunit_new_stream(struct kunit *test);
+
+/**
+ * kunit_stream_set_level(): sets the level that string should be printed at.
+ * @this: the stream being operated on.
+ * @level: the print level the stream is set to output to.
+ *
+ * Sets the print level at which the stream outputs.
+ */
+void kunit_stream_set_level(struct kunit_stream *this, const char *level);
+
+/**
+ * kunit_stream_add(): adds the formatted input to the internal buffer.
+ * @this: the stream being operated on.
+ * @fmt: printf style format string to append to stream.
+ *
+ * Appends the formatted string, @fmt, to the internal buffer.
+ */
+void __printf(2, 3) kunit_stream_add(struct kunit_stream *this,
+const char *fmt, ...);
+
+/**
+ * kunit_stream_append(): appends the contents of @other to @this.
+ * @this: the stream to which @other is appended.
+ * @other: the stream whose contents are appended to @this.
+ *
+ * Appends the contents of @other to @this.
+ */
+void kunit_stream_append(struct kunit_stream *this, struct kunit_stream 
*other);
+
+/**
+ * kunit_stream_commit(): prints out the internal buffer to the user.
+ * @this: the stream being operated on.
+ *
+ * Outputs the contents of the internal buffer as a kunit_printk formatted
+ * output.
+ */
+void kunit_stream_commit(struct kunit_stream *this);
+
+/**
+ * kunit_stream_clear(): clears the internal buffer.
+ * @this: the stream being operated on.
+ *
+ * Clears the contents of the internal buffer.
+ */
+void kunit_stream_clear(struct kunit_stream *this);
+
+#endif /* _KUNIT_KUNIT_STREAM_H */
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 819edd8db4e81..4668e8a635954 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -11,6 +11,7 @@
 
 #include 
 #include 
+#include 
 
 struct kunit_resource;
 
@@ -171,6 +172,7 @@ struct kunit {
void (*vprintk)(const struct kunit *test,
const char *level,
struct va_format *vaf);
+   void (*fail)(struct kunit *test, struct kunit_stream *stream);
 };
 
 int kunit_init_test(struct kunit *test, const char *name);
diff --git a/kunit/Makefile b/kunit/Makefile
index 275b565a0e81f..6ddc622ee6b1c 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_KUNIT) += test.o \
-   string-stream.o
+   string-stream.o \
+   kunit-stream.o
diff --git a/kunit/kunit-stream.c b/kunit/kunit-stream.c
new file mode 100644
index 0..93c14eec03844
--- /dev/null
+++ b/kunit/kunit-stream.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * C++ stream style string formatter and printer used in KUnit for outputting
+ * KUnit messages.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+#include 
+
+const char *kunit_stream_get_level(struct kunit_stream *this)
+{
+   unsigned long flags;
+   const char *level;
+
+   spin_lock_irqsave(>lock, flags);
+   level = this->level;
+   spin_unlock_irqrestore(>lock, flags);
+
+   return level;
+}
+
+void kunit_stream_set_level(struct kunit_stream *this, const char *level)
+{
+   unsigned long flags;
+
+   

[PATCH v2 07/17] kunit: test: add initial tests

2019-05-01 Thread Brendan Higgins
Add a test for string stream along with a simpler example.

Signed-off-by: Brendan Higgins 
---
 kunit/Kconfig  | 12 ++
 kunit/Makefile |  4 ++
 kunit/example-test.c   | 88 ++
 kunit/string-stream-test.c | 61 ++
 4 files changed, 165 insertions(+)
 create mode 100644 kunit/example-test.c
 create mode 100644 kunit/string-stream-test.c

diff --git a/kunit/Kconfig b/kunit/Kconfig
index 64480092b2c24..5cb500355c873 100644
--- a/kunit/Kconfig
+++ b/kunit/Kconfig
@@ -13,4 +13,16 @@ config KUNIT
  special hardware. For more information, please see
  Documentation/kunit/
 
+config KUNIT_TEST
+   bool "KUnit test for KUnit"
+   depends on KUNIT
+   help
+ Enables KUnit test to test KUnit.
+
+config KUNIT_EXAMPLE_TEST
+   bool "Example test for KUnit"
+   depends on KUNIT
+   help
+ Enables example KUnit test to demo features of KUnit.
+
 endmenu
diff --git a/kunit/Makefile b/kunit/Makefile
index 6ddc622ee6b1c..60a9ea6cb4697 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -1,3 +1,7 @@
 obj-$(CONFIG_KUNIT) += test.o \
string-stream.o \
kunit-stream.o
+
+obj-$(CONFIG_KUNIT_TEST) +=string-stream-test.o
+
+obj-$(CONFIG_KUNIT_EXAMPLE_TEST) +=example-test.o
diff --git a/kunit/example-test.c b/kunit/example-test.c
new file mode 100644
index 0..3947dd7c8f922
--- /dev/null
+++ b/kunit/example-test.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Example KUnit test to show how to use KUnit.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+
+/*
+ * This is the most fundamental element of KUnit, the test case. A test case
+ * makes a set EXPECTATIONs and ASSERTIONs about the behavior of some code; if
+ * any expectations or assertions are not met, the test fails; otherwise, the
+ * test passes.
+ *
+ * In KUnit, a test case is just a function with the signature
+ * `void (*)(struct kunit *)`. `struct kunit` is a context object that stores
+ * information about the current test.
+ */
+static void example_simple_test(struct kunit *test)
+{
+   /*
+* This is an EXPECTATION; it is how KUnit tests things. When you want
+* to test a piece of code, you set some expectations about what the
+* code should do. KUnit then runs the test and verifies that the code's
+* behavior matched what was expected.
+*/
+   KUNIT_EXPECT_EQ(test, 1 + 1, 2);
+}
+
+/*
+ * This is run once before each test case, see the comment on
+ * example_test_module for more information.
+ */
+static int example_test_init(struct kunit *test)
+{
+   kunit_info(test, "initializing\n");
+
+   return 0;
+}
+
+/*
+ * Here we make a list of all the test cases we want to add to the test module
+ * below.
+ */
+static struct kunit_case example_test_cases[] = {
+   /*
+* This is a helper to create a test case object from a test case
+* function; its exact function is not important to understand how to
+* use KUnit, just know that this is how you associate test cases with a
+* test module.
+*/
+   KUNIT_CASE(example_simple_test),
+   {},
+};
+
+/*
+ * This defines a suite or grouping of tests.
+ *
+ * Test cases are defined as belonging to the suite by adding them to
+ * `kunit_cases`.
+ *
+ * Often it is desirable to run some function which will set up things which
+ * will be used by every test; this is accomplished with an `init` function
+ * which runs before each test case is invoked. Similarly, an `exit` function
+ * may be specified which runs after every test case and can be used to for
+ * cleanup. For clarity, running tests in a test module would behave as 
follows:
+ *
+ * module.init(test);
+ * module.test_case[0](test);
+ * module.exit(test);
+ * module.init(test);
+ * module.test_case[1](test);
+ * module.exit(test);
+ * ...;
+ */
+static struct kunit_module example_test_module = {
+   .name = "example",
+   .init = example_test_init,
+   .test_cases = example_test_cases,
+};
+
+/*
+ * This registers the above test module telling KUnit that this is a suite of
+ * tests that need to be run.
+ */
+module_test(example_test_module);
diff --git a/kunit/string-stream-test.c b/kunit/string-stream-test.c
new file mode 100644
index 0..b2a98576797c9
--- /dev/null
+++ b/kunit/string-stream-test.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for struct string_stream.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+#include 
+
+static void string_stream_test_get_string(struct kunit *test)
+{
+   struct string_stream *stream = new_string_stream();
+   char *output;
+
+   string_stream_add(stream, "Foo");
+   

[PATCH v2 03/17] kunit: test: add string_stream a std::stream like string builder

2019-05-01 Thread Brendan Higgins
A number of test features need to do pretty complicated string printing
where it may not be possible to rely on a single preallocated string
with parameters.

So provide a library for constructing the string as you go similar to
C++'s std::string.

Signed-off-by: Brendan Higgins 
---
 include/kunit/string-stream.h |  51 
 kunit/Makefile|   3 +-
 kunit/string-stream.c | 144 ++
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 include/kunit/string-stream.h
 create mode 100644 kunit/string-stream.c

diff --git a/include/kunit/string-stream.h b/include/kunit/string-stream.h
new file mode 100644
index 0..567a4629406da
--- /dev/null
+++ b/include/kunit/string-stream.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * C++ stream style string builder used in KUnit for building messages.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_STRING_STREAM_H
+#define _KUNIT_STRING_STREAM_H
+
+#include 
+#include 
+#include 
+#include 
+
+struct string_stream_fragment {
+   struct list_head node;
+   char *fragment;
+};
+
+struct string_stream {
+   size_t length;
+   struct list_head fragments;
+
+   /* length and fragments are protected by this lock */
+   spinlock_t lock;
+   struct kref refcount;
+};
+
+struct string_stream *new_string_stream(void);
+
+void destroy_string_stream(struct string_stream *stream);
+
+void string_stream_get(struct string_stream *stream);
+
+int string_stream_put(struct string_stream *stream);
+
+int string_stream_add(struct string_stream *this, const char *fmt, ...);
+
+int string_stream_vadd(struct string_stream *this,
+  const char *fmt,
+  va_list args);
+
+char *string_stream_get_string(struct string_stream *this);
+
+void string_stream_clear(struct string_stream *this);
+
+bool string_stream_is_empty(struct string_stream *this);
+
+#endif /* _KUNIT_STRING_STREAM_H */
diff --git a/kunit/Makefile b/kunit/Makefile
index 5efdc4dea2c08..275b565a0e81f 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_KUNIT) += test.o
+obj-$(CONFIG_KUNIT) += test.o \
+   string-stream.o
diff --git a/kunit/string-stream.c b/kunit/string-stream.c
new file mode 100644
index 0..7018194ecf2fa
--- /dev/null
+++ b/kunit/string-stream.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * C++ stream style string builder used in KUnit for building messages.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+#include 
+
+int string_stream_vadd(struct string_stream *this,
+  const char *fmt,
+  va_list args)
+{
+   struct string_stream_fragment *fragment;
+   int len;
+   va_list args_for_counting;
+   unsigned long flags;
+
+   /* Make a copy because `vsnprintf` could change it */
+   va_copy(args_for_counting, args);
+
+   /* Need space for null byte. */
+   len = vsnprintf(NULL, 0, fmt, args_for_counting) + 1;
+
+   va_end(args_for_counting);
+
+   fragment = kmalloc(sizeof(*fragment), GFP_KERNEL);
+   if (!fragment)
+   return -ENOMEM;
+
+   fragment->fragment = kmalloc(len, GFP_KERNEL);
+   if (!fragment->fragment) {
+   kfree(fragment);
+   return -ENOMEM;
+   }
+
+   len = vsnprintf(fragment->fragment, len, fmt, args);
+   spin_lock_irqsave(>lock, flags);
+   this->length += len;
+   list_add_tail(>node, >fragments);
+   spin_unlock_irqrestore(>lock, flags);
+   return 0;
+}
+
+int string_stream_add(struct string_stream *this, const char *fmt, ...)
+{
+   va_list args;
+   int result;
+
+   va_start(args, fmt);
+   result = string_stream_vadd(this, fmt, args);
+   va_end(args);
+   return result;
+}
+
+void string_stream_clear(struct string_stream *this)
+{
+   struct string_stream_fragment *fragment, *fragment_safe;
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+   list_for_each_entry_safe(fragment,
+fragment_safe,
+>fragments,
+node) {
+   list_del(>node);
+   kfree(fragment->fragment);
+   kfree(fragment);
+   }
+   this->length = 0;
+   spin_unlock_irqrestore(>lock, flags);
+}
+
+char *string_stream_get_string(struct string_stream *this)
+{
+   struct string_stream_fragment *fragment;
+   size_t buf_len = this->length + 1; /* +1 for null byte. */
+   char *buf;
+   unsigned long flags;
+
+   buf = kzalloc(buf_len, GFP_KERNEL);
+   if (!buf)
+   return NULL;
+
+   spin_lock_irqsave(>lock, flags);
+   list_for_each_entry(fragment, 

[PATCH v2 02/17] kunit: test: add test resource management API

2019-05-01 Thread Brendan Higgins
Create a common API for test managed resources like memory and test
objects. A lot of times a test will want to set up infrastructure to be
used in test cases; this could be anything from just wanting to allocate
some memory to setting up a driver stack; this defines facilities for
creating "test resources" which are managed by the test infrastructure
and are automatically cleaned up at the conclusion of the test.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 109 +++
 kunit/test.c |  95 +
 2 files changed, 204 insertions(+)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 23c2ebedd6dd9..819edd8db4e81 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -12,6 +12,69 @@
 #include 
 #include 
 
+struct kunit_resource;
+
+typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *);
+typedef void (*kunit_resource_free_t)(struct kunit_resource *);
+
+/**
+ * struct kunit_resource - represents a *test managed resource*
+ * @allocation: for the user to store arbitrary data.
+ * @free: a user supplied function to free the resource. Populated by
+ * kunit_alloc_resource().
+ *
+ * Represents a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * struct kunit_kmalloc_params {
+ * size_t size;
+ * gfp_t gfp;
+ * };
+ *
+ * static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
+ * {
+ * struct kunit_kmalloc_params *params = context;
+ * res->allocation = kmalloc(params->size, params->gfp);
+ *
+ * if (!res->allocation)
+ * return -ENOMEM;
+ *
+ * return 0;
+ * }
+ *
+ * static void kunit_kmalloc_free(struct kunit_resource *res)
+ * {
+ * kfree(res->allocation);
+ * }
+ *
+ * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
+ * {
+ * struct kunit_kmalloc_params params;
+ * struct kunit_resource *res;
+ *
+ * params.size = size;
+ * params.gfp = gfp;
+ *
+ * res = kunit_alloc_resource(test, kunit_kmalloc_init,
+ * kunit_kmalloc_free, );
+ * if (res)
+ * return res->allocation;
+ * else
+ * return NULL;
+ * }
+ */
+struct kunit_resource {
+   void *allocation;
+   kunit_resource_free_t free;
+
+   /* private: internal use only. */
+   struct list_head node;
+};
+
 struct kunit;
 
 /**
@@ -104,6 +167,7 @@ struct kunit {
const char *name; /* Read only after initialization! */
spinlock_t lock; /* Gaurds all mutable test state. */
bool success; /* Protected by lock. */
+   struct list_head resources; /* Protected by lock. */
void (*vprintk)(const struct kunit *test,
const char *level,
struct va_format *vaf);
@@ -127,6 +191,51 @@ int kunit_run_tests(struct kunit_module *module);
} \
late_initcall(module_kunit_init##module)
 
+/**
+ * kunit_alloc_resource() - Allocates a *test managed resource*.
+ * @test: The test context object.
+ * @init: a user supplied function to initialize the resource.
+ * @free: a user supplied function to free the resource.
+ * @context: for the user to pass in arbitrary data to the init function.
+ *
+ * Allocates a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case. See  kunit_resource for an
+ * example.
+ */
+struct kunit_resource *kunit_alloc_resource(struct kunit *test,
+   kunit_resource_init_t init,
+   kunit_resource_free_t free,
+   void *context);
+
+void kunit_free_resource(struct kunit *test, struct kunit_resource *res);
+
+/**
+ * kunit_kmalloc() - Like kmalloc() except the allocation is *test managed*.
+ * @test: The test context object.
+ * @size: The size in bytes of the desired memory.
+ * @gfp: flags passed to underlying kmalloc().
+ *
+ * Just like `kmalloc(...)`, except the allocation is managed by the test case
+ * and is automatically cleaned up after the test case concludes. See 
+ * kunit_resource for more information.
+ */
+void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp);
+
+/**
+ * kunit_kzalloc() - Just like kunit_kmalloc(), but zeroes the allocation.
+ * @test: The test context object.
+ * @size: The size in bytes of the desired memory.
+ * @gfp: flags passed to underlying kmalloc().
+ *
+ * See kzalloc() and kunit_kmalloc() for more information.
+ */
+static inline void *kunit_kzalloc(struct kunit *test, size_t size, gfp_t gfp)
+{
+   return kunit_kmalloc(test, size, gfp | __GFP_ZERO);
+}
+
+void 

[PATCH v2 00/17] kunit: introduce KUnit, the Linux kernel unit testing framework

2019-05-01 Thread Brendan Higgins
## TLDR

I rebased the last patchset on 5.1-rc7 in hopes that we can get this in
5.2.

Shuah, I think you, Greg KH, and myself talked off thread, and we agreed
we would merge through your tree when the time came? Am I remembering
correctly?

## Background

This patch set proposes KUnit, a lightweight unit testing and mocking
framework for the Linux kernel.

Unlike Autotest and kselftest, KUnit is a true unit testing framework;
it does not require installing the kernel on a test machine or in a VM
and does not require tests to be written in userspace running on a host
kernel. Additionally, KUnit is fast: From invocation to completion KUnit
can run several dozen tests in under a second. Currently, the entire
KUnit test suite for KUnit runs in under a second from the initial
invocation (build time excluded).

KUnit is heavily inspired by JUnit, Python's unittest.mock, and
Googletest/Googlemock for C++. KUnit provides facilities for defining
unit test cases, grouping related test cases into test suites, providing
common infrastructure for running tests, mocking, spying, and much more.

## What's so special about unit testing?

A unit test is supposed to test a single unit of code in isolation,
hence the name. There should be no dependencies outside the control of
the test; this means no external dependencies, which makes tests orders
of magnitudes faster. Likewise, since there are no external dependencies,
there are no hoops to jump through to run the tests. Additionally, this
makes unit tests deterministic: a failing unit test always indicates a
problem. Finally, because unit tests necessarily have finer granularity,
they are able to test all code paths easily solving the classic problem
of difficulty in exercising error handling code.

## Is KUnit trying to replace other testing frameworks for the kernel?

No. Most existing tests for the Linux kernel are end-to-end tests, which
have their place. A well tested system has lots of unit tests, a
reasonable number of integration tests, and some end-to-end tests. KUnit
is just trying to address the unit test space which is currently not
being addressed.

## More information on KUnit

There is a bunch of documentation near the end of this patch set that
describes how to use KUnit and best practices for writing unit tests.
For convenience I am hosting the compiled docs here:
https://google.github.io/kunit-docs/third_party/kernel/docs/
Additionally for convenience, I have applied these patches to a branch:
https://kunit.googlesource.com/linux/+/kunit/rfc/v5.1-rc7/v1
The repo may be cloned with:
git clone https://kunit.googlesource.com/linux
This patchset is on the kunit/rfc/v5.1-rc7/v1 branch.

## Changes Since Last Version

None. I just rebased the last patchset on v5.1-rc7.

-- 
2.21.0.593.g511ec345e18-goog

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[v4 1/2] device-dax: fix memory and resource leak if hotplug fails

2019-05-01 Thread Pavel Tatashin
When add_memory() function fails, the resource and the memory should be
freed.

Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like 
normal RAM")

Signed-off-by: Pavel Tatashin 
Reviewed-by: Dave Hansen 
---
 drivers/dax/kmem.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
index a02318c6d28a..4c0131857133 100644
--- a/drivers/dax/kmem.c
+++ b/drivers/dax/kmem.c
@@ -66,8 +66,11 @@ int dev_dax_kmem_probe(struct device *dev)
new_res->name = dev_name(dev);
 
rc = add_memory(numa_node, new_res->start, resource_size(new_res));
-   if (rc)
+   if (rc) {
+   release_resource(new_res);
+   kfree(new_res);
return rc;
+   }
 
return 0;
 }
-- 
2.21.0

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[v4 0/2] "Hotremove" persistent memory

2019-05-01 Thread Pavel Tatashin
Changelog:
v4
- Addressed comments from Dave Hansen

v3
- Addressed comments from David Hildenbrand. Don't release
  lock_device_hotplug after checking memory status, and rename
  memblock_offlined_cb() to check_memblock_offlined_cb()

v2
- Dan Williams mentioned that drv->remove() return is ignored
  by unbind. Unbind always succeeds. Because we cannot guarantee
  that memory can be offlined from the driver, don't even
  attempt to do so. Simply check that every section is offlined
  beforehand and only then proceed with removing dax memory.

---

Recently, adding a persistent memory to be used like a regular RAM was
added to Linux. This work extends this functionality to also allow hot
removing persistent memory.

We (Microsoft) have an important use case for this functionality.

The requirement is for physical machines with small amount of RAM (~8G)
to be able to reboot in a very short period of time (<1s). Yet, there is
a userland state that is expensive to recreate (~2G).

The solution is to boot machines with 2G preserved for persistent
memory.

Copy the state, and hotadd the persistent memory so machine still has
all 8G available for runtime. Before reboot, offline and hotremove
device-dax 2G, copy the memory that is needed to be preserved to pmem0
device, and reboot.

The series of operations look like this:

1. After boot restore /dev/pmem0 to ramdisk to be consumed by apps.
   and free ramdisk.
2. Convert raw pmem0 to devdax
   ndctl create-namespace --mode devdax --map mem -e namespace0.0 -f
3. Hotadd to System RAM
   echo dax0.0 > /sys/bus/dax/drivers/device_dax/unbind
   echo dax0.0 > /sys/bus/dax/drivers/kmem/new_id
   echo online_movable > /sys/devices/system/memoryXXX/state
4. Before reboot hotremove device-dax memory from System RAM
   echo offline > /sys/devices/system/memoryXXX/state
   echo dax0.0 > /sys/bus/dax/drivers/kmem/unbind
5. Create raw pmem0 device
   ndctl create-namespace --mode raw  -e namespace0.0 -f
6. Copy the state that was stored by apps to ramdisk to pmem device
7. Do kexec reboot or reboot through firmware if firmware does not
   zero memory in pmem0 region (These machines have only regular
   volatile memory). So to have pmem0 device either memmap kernel
   parameter is used, or devices nodes in dtb are specified.

Pavel Tatashin (2):
  device-dax: fix memory and resource leak if hotplug fails
  device-dax: "Hotremove" persistent memory that is used like normal RAM

 drivers/dax/dax-private.h |   2 +
 drivers/dax/kmem.c| 104 --
 2 files changed, 101 insertions(+), 5 deletions(-)

-- 
2.21.0

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm


[v4 2/2] device-dax: "Hotremove" persistent memory that is used like normal RAM

2019-05-01 Thread Pavel Tatashin
It is now allowed to use persistent memory like a regular RAM, but
currently there is no way to remove this memory until machine is
rebooted.

This work expands the functionality to also allows hotremoving
previously hotplugged persistent memory, and recover the device for use
for other purposes.

To hotremove persistent memory, the management software must first
offline all memory blocks of dax region, and than unbind it from
device-dax/kmem driver. So, operations should look like this:

echo offline > echo offline > /sys/devices/system/memory/memoryN/state
...
echo dax0.0 > /sys/bus/dax/drivers/kmem/unbind

Note: if unbind is done without offlining memory beforehand, it won't be
possible to do dax0.0 hotremove, and dax's memory is going to be part of
System RAM until reboot.

Signed-off-by: Pavel Tatashin 
---
 drivers/dax/dax-private.h |  2 +
 drivers/dax/kmem.c| 99 +--
 2 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
index a45612148ca0..999aaf3a29b3 100644
--- a/drivers/dax/dax-private.h
+++ b/drivers/dax/dax-private.h
@@ -53,6 +53,7 @@ struct dax_region {
  * @pgmap - pgmap for memmap setup / lifetime (driver owned)
  * @ref: pgmap reference count (driver owned)
  * @cmp: @ref final put completion (driver owned)
+ * @dax_mem_res: physical address range of hotadded DAX memory
  */
 struct dev_dax {
struct dax_region *region;
@@ -62,6 +63,7 @@ struct dev_dax {
struct dev_pagemap pgmap;
struct percpu_ref ref;
struct completion cmp;
+   struct resource *dax_kmem_res;
 };
 
 static inline struct dev_dax *to_dev_dax(struct device *dev)
diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
index 4c0131857133..72b868066026 100644
--- a/drivers/dax/kmem.c
+++ b/drivers/dax/kmem.c
@@ -71,21 +71,112 @@ int dev_dax_kmem_probe(struct device *dev)
kfree(new_res);
return rc;
}
+   dev_dax->dax_kmem_res = new_res;
 
return 0;
 }
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+static int
+check_devdax_mem_offlined_cb(struct memory_block *mem, void *arg)
+{
+   /* Memory block device */
+   struct device *mem_dev = >dev;
+   bool is_offline;
+
+   device_lock(mem_dev);
+   is_offline = mem_dev->offline;
+   device_unlock(mem_dev);
+
+   /*
+* Check that device-dax's memory_blocks are offline. If a memory_block
+* is not offline a warning is printed and an error is returned.
+*/
+   if (!is_offline) {
+   /* Dax device device */
+   struct device *dev = (struct device *)arg;
+   struct dev_dax *dev_dax = to_dev_dax(dev);
+   struct resource *res = _dax->region->res;
+   unsigned long spfn = section_nr_to_pfn(mem->start_section_nr);
+   unsigned long epfn = section_nr_to_pfn(mem->end_section_nr) +
+  PAGES_PER_SECTION - 1;
+   phys_addr_t spa = spfn << PAGE_SHIFT;
+   phys_addr_t epa = epfn << PAGE_SHIFT;
+
+   dev_err(dev,
+   "DAX region %pR cannot be hotremoved until the next 
reboot. Memory block [%pa-%pa] is not offline.\n",
+   res, , );
+
+   return -EBUSY;
+   }
+
+   return 0;
+}
+
+static int dev_dax_kmem_remove(struct device *dev)
+{
+   struct dev_dax *dev_dax = to_dev_dax(dev);
+   struct resource *res = dev_dax->dax_kmem_res;
+   resource_size_t kmem_start;
+   resource_size_t kmem_size;
+   unsigned long start_pfn;
+   unsigned long end_pfn;
+   int rc;
+
+   kmem_start = res->start;
+   kmem_size = resource_size(res);
+   start_pfn = kmem_start >> PAGE_SHIFT;
+   end_pfn = start_pfn + (kmem_size >> PAGE_SHIFT) - 1;
+
+   /*
+* Keep hotplug lock while checking memory state, and also required
+* during __remove_memory() call. Admin can't change memory state via
+* sysfs while this lock is kept.
+*/
+   lock_device_hotplug();
+
+   /*
+* Walk and check that every singe memory_block of dax region is
+* offline. Hotremove can succeed only when every memory_block is
+* offlined beforehand.
+*/
+   rc = walk_memory_range(start_pfn, end_pfn, dev,
+  check_devdax_mem_offlined_cb);
+
+   /*
+* If admin has not offlined memory beforehand, we cannot hotremove dax.
+* Unfortunately, because unbind will still succeed there is no way for
+* user to hotremove dax after this.
+*/
+   if (rc) {
+   unlock_device_hotplug();
+   return rc;
+   }
+
+   /* Hotremove memory, cannot fail because memory is already offlined */
+   __remove_memory(dev_dax->target_node, kmem_start, kmem_size);
+   unlock_device_hotplug();
+
+   /* Release and 

[PATCH] acpi/nfit: Use the correct style for SPDX License Identifier

2019-05-01 Thread Nishad Kamdar
This patch corrects the SPDX License Identifier style
in drivers/acpi/nfit/intel.h. For C header files
Documentation/process/license-rules.rst mandates C-like comments
(opposed to C source files where C++ style should be used)

Changes made by using a script provided by Joe Perches here:
https://lkml.org/lkml/2019/2/7/46

Suggested-by: Joe Perches 
Signed-off-by: Nishad Kamdar 
---
 drivers/acpi/nfit/intel.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/acpi/nfit/intel.h b/drivers/acpi/nfit/intel.h
index 0aca682ab9d7..8f5461c1dd9d 100644
--- a/drivers/acpi/nfit/intel.h
+++ b/drivers/acpi/nfit/intel.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright(c) 2018 Intel Corporation. All rights reserved.
  * Intel specific definitions for NVDIMM Firmware Interface Table - NFIT
-- 
2.17.1

___
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm