Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Documentation/dev-tools/kunit/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ things to try.
re-run kunit_tool.
5. Try to run ``make ARCH=um defconfig`` before running ``kunit.py run``. This
may help clean up any residual config items which could be causing problems.
6. Finally, try running KUnit outside UML. KUnit and KUnit tests can run be
6. Finally, try running KUnit outside UML. KUnit and KUnit tests can be
built into any kernel, or can be built as a module and loaded at runtime.
Doing so should allow you to determine if UML is causing the issue you're
seeing. When tests are built-in, they will execute when the kernel boots, and
Expand Down
18 changes: 9 additions & 9 deletions Documentation/dev-tools/kunit/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,17 @@ An example Kconfig entry:

.. code-block:: none

config FOO_KUNIT_TEST
tristate "KUnit test for foo" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
help
This builds unit tests for foo.
config FOO_KUNIT_TEST
tristate "KUnit test for foo" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
help
This builds unit tests for foo.

For more information on KUnit and unit tests in general, please refer
to the KUnit documentation in Documentation/dev-tools/kunit
For more information on KUnit and unit tests in general, please refer
to the KUnit documentation in Documentation/dev-tools/kunit/.

If unsure, say N
If unsure, say N.


Test File and Module Names
Expand Down
10 changes: 5 additions & 5 deletions Documentation/dev-tools/kunit/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ behavior of a function called ``add``; the first parameter is always of type
the second parameter, in this case, is what the value is expected to be; the
last value is what the value actually is. If ``add`` passes all of these
expectations, the test case, ``add_test_basic`` will pass; if any one of these
expectations fail, the test case will fail.
expectations fails, the test case will fail.

It is important to understand that a test case *fails* when any expectation is
violated; however, the test will continue running, potentially trying other
Expand Down Expand Up @@ -202,7 +202,7 @@ Example:
kunit_test_suite(example_test_suite);

In the above example the test suite, ``example_test_suite``, would run the test
cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``,
cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``;
each would have ``example_test_init`` called immediately before it and would
have ``example_test_exit`` called immediately after it.
``kunit_test_suite(example_test_suite)`` registers the test suite with the
Expand All @@ -229,7 +229,7 @@ through some sort of indirection where a function is exposed as part of an API
such that the definition of that function can be changed without affecting the
rest of the code base. In the kernel this primarily comes from two constructs,
classes, structs that contain function pointers that are provided by the
implementer, and architecture specific functions which have definitions selected
implementer, and architecture-specific functions which have definitions selected
at compile time.

Classes
Expand Down Expand Up @@ -459,7 +459,7 @@ KUnit on non-UML architectures
By default KUnit uses UML as a way to provide dependencies for code under test.
Under most circumstances KUnit's usage of UML should be treated as an
implementation detail of how KUnit works under the hood. Nevertheless, there
are instances where being able to run architecture specific code or test
are instances where being able to run architecture-specific code or test
against real hardware is desirable. For these reasons KUnit supports running on
other architectures.

Expand Down Expand Up @@ -599,7 +599,7 @@ writing normal KUnit tests. One special caveat is that you have to reset
hardware state in between test cases; if this is not possible, you may only be
able to run one test case per invocation.

.. TODO(brendanhiggins@google.com): Add an actual example of an architecture
.. TODO(brendanhiggins@google.com): Add an actual example of an architecture-
dependent KUnit test.

KUnit debugfs representation
Expand Down
13 changes: 12 additions & 1 deletion fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,18 @@ static int freeze_go_sync(struct gfs2_glock *gl)
int error = 0;
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

if (gl->gl_req == LM_ST_EXCLUSIVE && !gfs2_withdrawn(sdp)) {
/*
* We need to check gl_state == LM_ST_SHARED here and not gl_req ==
* LM_ST_EXCLUSIVE. That's because when any node does a freeze,
* all the nodes should have the freeze glock in SH mode and they all
* call do_xmote: One for EX and the others for UN. They ALL must
* freeze locally, and they ALL must queue freeze work. The freeze_work
* calls freeze_func, which tries to reacquire the freeze glock in SH,
* effectively waiting for the thaw on the node who holds it in EX.
* Once thawed, the work func acquires the freeze glock in
* SH and everybody goes back to thawed.
*/
if (gl->gl_state == LM_ST_SHARED && !gfs2_withdrawn(sdp)) {
atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
error = freeze_super(sdp->sd_vfs);
if (error) {
Expand Down
2 changes: 1 addition & 1 deletion include/kunit/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -1105,7 +1105,7 @@ do { \
KUNIT_ASSERTION(test, \
strcmp(__left, __right) op 0, \
kunit_binary_str_assert, \
KUNIT_INIT_BINARY_ASSERT_STRUCT(test, \
KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \
assert_type, \
#op, \
#left, \
Expand Down
3 changes: 2 additions & 1 deletion include/trace/events/sunrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ DECLARE_EVENT_CLASS(rpc_xdr_buf_class,

TP_fast_assign(
__entry->task_id = task->tk_pid;
__entry->client_id = task->tk_client->cl_clid;
__entry->client_id = task->tk_client ?
task->tk_client->cl_clid : -1;
__entry->head_base = xdr->head[0].iov_base;
__entry->head_len = xdr->head[0].iov_len;
__entry->tail_base = xdr->tail[0].iov_base;
Expand Down
1 change: 0 additions & 1 deletion tools/testing/kunit/.gitattributes

This file was deleted.

27 changes: 13 additions & 14 deletions tools/testing/kunit/kunit.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import sys
import os
import time
import shutil

from collections import namedtuple
from enum import Enum, auto
Expand Down Expand Up @@ -44,11 +43,6 @@ class KunitStatus(Enum):
BUILD_FAILURE = auto()
TEST_FAILURE = auto()

def create_default_kunitconfig():
if not os.path.exists(kunit_kernel.kunitconfig_path):
shutil.copyfile('arch/um/configs/kunit_defconfig',
kunit_kernel.kunitconfig_path)

def get_kernel_root_path():
parts = sys.argv[0] if not __file__ else __file__
parts = os.path.realpath(parts).split('tools/testing/kunit')
Expand All @@ -61,7 +55,6 @@ def config_tests(linux: kunit_kernel.LinuxSourceTree,
kunit_parser.print_with_timestamp('Configuring KUnit Kernel ...')

config_start = time.time()
create_default_kunitconfig()
success = linux.build_reconfig(request.build_dir, request.make_options)
config_end = time.time()
if not success:
Expand Down Expand Up @@ -262,12 +255,12 @@ def main(argv, linux=None):
if not os.path.exists(cli_args.build_dir):
os.mkdir(cli_args.build_dir)

if not os.path.exists(kunit_kernel.kunitconfig_path):
create_default_kunitconfig()

if not linux:
linux = kunit_kernel.LinuxSourceTree()

linux.create_kunitconfig(cli_args.build_dir)
linux.read_kunitconfig(cli_args.build_dir)

request = KunitRequest(cli_args.raw_output,
cli_args.timeout,
cli_args.jobs,
Expand All @@ -283,12 +276,12 @@ def main(argv, linux=None):
not os.path.exists(cli_args.build_dir)):
os.mkdir(cli_args.build_dir)

if not os.path.exists(kunit_kernel.kunitconfig_path):
create_default_kunitconfig()

if not linux:
linux = kunit_kernel.LinuxSourceTree()

linux.create_kunitconfig(cli_args.build_dir)
linux.read_kunitconfig(cli_args.build_dir)

request = KunitConfigRequest(cli_args.build_dir,
cli_args.make_options)
result = config_tests(linux, request)
Expand All @@ -301,6 +294,9 @@ def main(argv, linux=None):
if not linux:
linux = kunit_kernel.LinuxSourceTree()

linux.create_kunitconfig(cli_args.build_dir)
linux.read_kunitconfig(cli_args.build_dir)

request = KunitBuildRequest(cli_args.jobs,
cli_args.build_dir,
cli_args.alltests,
Expand All @@ -315,6 +311,9 @@ def main(argv, linux=None):
if not linux:
linux = kunit_kernel.LinuxSourceTree()

linux.create_kunitconfig(cli_args.build_dir)
linux.read_kunitconfig(cli_args.build_dir)

exec_request = KunitExecRequest(cli_args.timeout,
cli_args.build_dir,
cli_args.alltests)
Expand All @@ -337,7 +336,7 @@ def main(argv, linux=None):
kunit_output = f.read().splitlines()
request = KunitParseRequest(cli_args.raw_output,
kunit_output,
cli_args.build_dir,
None,
cli_args.json)
result = parse_tests(request)
if result.status != KunitStatus.SUCCESS:
Expand Down
53 changes: 40 additions & 13 deletions tools/testing/kunit/kunit_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
# Author: Felix Guo <felixguoxiuping@gmail.com>
# Author: Brendan Higgins <brendanhiggins@google.com>


import logging
import subprocess
import os
import shutil
import signal

from contextlib import ExitStack
Expand All @@ -18,8 +18,10 @@
import kunit_parser

KCONFIG_PATH = '.config'
kunitconfig_path = '.kunitconfig'
KUNITCONFIG_PATH = '.kunitconfig'
DEFAULT_KUNITCONFIG_PATH = 'arch/um/configs/kunit_defconfig'
BROKEN_ALLCONFIG_PATH = 'tools/testing/kunit/configs/broken_on_uml.config'
OUTFILE_PATH = 'test.log'

class ConfigError(Exception):
"""Represents an error trying to configure the Linux kernel."""
Expand Down Expand Up @@ -82,36 +84,51 @@ def make(self, jobs, build_dir, make_options):
if build_dir:
command += ['O=' + build_dir]
try:
subprocess.check_output(command, stderr=subprocess.STDOUT)
proc = subprocess.Popen(command,
stderr=subprocess.PIPE,
stdout=subprocess.DEVNULL)
except OSError as e:
raise BuildError('Could not call execute make: ' + str(e))
except subprocess.CalledProcessError as e:
raise BuildError(e.output.decode())

def linux_bin(self, params, timeout, build_dir, outfile):
raise BuildError('Could not call make command: ' + str(e))
_, stderr = proc.communicate()
if proc.returncode != 0:
raise BuildError(stderr.decode())
if stderr: # likely only due to build warnings
print(stderr.decode())

def linux_bin(self, params, timeout, build_dir):
"""Runs the Linux UML binary. Must be named 'linux'."""
linux_bin = './linux'
if build_dir:
linux_bin = os.path.join(build_dir, 'linux')
outfile = get_outfile_path(build_dir)
with open(outfile, 'w') as output:
process = subprocess.Popen([linux_bin] + params,
stdout=output,
stderr=subprocess.STDOUT)
process.wait(timeout)


def get_kconfig_path(build_dir):
kconfig_path = KCONFIG_PATH
if build_dir:
kconfig_path = os.path.join(build_dir, KCONFIG_PATH)
return kconfig_path

def get_kunitconfig_path(build_dir):
kunitconfig_path = KUNITCONFIG_PATH
if build_dir:
kunitconfig_path = os.path.join(build_dir, KUNITCONFIG_PATH)
return kunitconfig_path

def get_outfile_path(build_dir):
outfile_path = OUTFILE_PATH
if build_dir:
outfile_path = os.path.join(build_dir, OUTFILE_PATH)
return outfile_path

class LinuxSourceTree(object):
"""Represents a Linux kernel source tree with KUnit tests."""

def __init__(self):
self._kconfig = kunit_config.Kconfig()
self._kconfig.read_from_file(kunitconfig_path)
self._ops = LinuxSourceTreeOperations()
signal.signal(signal.SIGINT, self.signal_handler)

Expand All @@ -123,6 +140,16 @@ def clean(self):
return False
return True

def create_kunitconfig(self, build_dir, defconfig=DEFAULT_KUNITCONFIG_PATH):
kunitconfig_path = get_kunitconfig_path(build_dir)
if not os.path.exists(kunitconfig_path):
shutil.copyfile(defconfig, kunitconfig_path)

def read_kunitconfig(self, build_dir):
kunitconfig_path = get_kunitconfig_path(build_dir)
self._kconfig = kunit_config.Kconfig()
self._kconfig.read_from_file(kunitconfig_path)

def validate_config(self, build_dir):
kconfig_path = get_kconfig_path(build_dir)
validated_kconfig = kunit_config.Kconfig()
Expand Down Expand Up @@ -178,8 +205,8 @@ def build_um_kernel(self, alltests, jobs, build_dir, make_options):

def run_kernel(self, args=[], build_dir='', timeout=None):
args.extend(['mem=1G'])
outfile = 'test.log'
self._ops.linux_bin(args, timeout, build_dir, outfile)
self._ops.linux_bin(args, timeout, build_dir)
outfile = get_outfile_path(build_dir)
subprocess.call(['stty', 'sane'])
with open(outfile, 'r') as file:
for line in file:
Expand Down
Loading