summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-11-28 15:08:27 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2019-11-28 15:08:27 -0500
commitffced87f08a9ff929f78fd941536d4f88507588a (patch)
treeb70119539d5013bc42eba318dc52731b64ede2ad
parent8c20176f2ce40fc8b0151e5a7d17561dd0eda0b5 (diff)
parent780de81b36188b141e35519d80755a83bfe5ea0b (diff)
Merge commit '780de81b36'
-rw-r--r--INSTALL34
-rw-r--r--Makefile6
-rw-r--r--bcachefs.c2
-rw-r--r--cmd_fusemount.c4
-rw-r--r--tests/test_fixture.py6
-rw-r--r--tests/test_fuse.py11
-rw-r--r--tests/util.py47
7 files changed, 96 insertions, 14 deletions
diff --git a/INSTALL b/INSTALL
index 46833a3..0c37c4a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,3 +1,4 @@
+-- Getting started --
Dependencies:
@@ -20,3 +21,36 @@ On debian, you can install these with
uuid-dev zlib1g-dev valgrind
Then, just make && make install
+
+
+-- Experimental features --
+
+Experimental fuse support is currently disabled by default. Fuse support is at
+an early stage and may corrupt your filesystem, so it should only be used for
+testing. To enable, you'll also need to add:
+
+* libfuse3
+
+On debian:
+ apt install -y libfuse3-dev
+
+Then, make using the BCACHEFS_FUSE environment variable:
+
+BCACHEFS_FUSE=1 make &&
+
+
+-- Tests --
+
+Some tests are available to validate the "bcachefs" binary. The tests depend
+on python3 pytest.
+
+On debian:
+ apt install -u python3-pytest
+
+Then, you can run the tests via:
+
+ make check
+
+Optionally, you may wish to run tests in parallel using python3-pytest-xdist:
+
+ cd tests; pytest-3 -n4
diff --git a/Makefile b/Makefile
index eb2798f..adea761 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,11 @@ ifdef D
CFLAGS+=-DCONFIG_BCACHEFS_DEBUG=y
endif
-PKGCONFIG_LIBS="blkid uuid liburcu libsodium zlib liblz4 libzstd fuse3"
+PKGCONFIG_LIBS="blkid uuid liburcu libsodium zlib liblz4 libzstd"
+ifdef BCACHEFS_FUSE
+ PKGCONFIG_LIBS+="fuse3"
+ CFLAGS+=-DBCACHEFS_FUSE
+endif
PKGCONFIG_CFLAGS:=$(shell $(PKG_CONFIG) --cflags $(PKGCONFIG_LIBS))
ifeq (,$(PKGCONFIG_CFLAGS))
diff --git a/bcachefs.c b/bcachefs.c
index 8840d51..03ebfd2 100644
--- a/bcachefs.c
+++ b/bcachefs.c
@@ -203,8 +203,10 @@ int main(int argc, char *argv[])
if (!strcmp(cmd, "setattr"))
return cmd_setattr(argc, argv);
+#ifdef BCACHEFS_FUSE
if (!strcmp(cmd, "fusemount"))
return cmd_fusemount(argc, argv);
+#endif
if (!strcmp(cmd, "--help")) {
usage();
diff --git a/cmd_fusemount.c b/cmd_fusemount.c
index 96a2339..4e4c24c 100644
--- a/cmd_fusemount.c
+++ b/cmd_fusemount.c
@@ -1,3 +1,5 @@
+#ifdef BCACHEFS_FUSE
+
#include <errno.h>
#include <float.h>
#include <getopt.h>
@@ -1262,3 +1264,5 @@ out:
return ret ? 1 : 0;
}
+
+#endif /* BCACHEFS_FUSE */
diff --git a/tests/test_fixture.py b/tests/test_fixture.py
index 74a896b..d8d3819 100644
--- a/tests/test_fixture.py
+++ b/tests/test_fixture.py
@@ -29,26 +29,32 @@ def test_segfault():
ret = util.run(helper, 'segfault')
assert ret.returncode == -signal.SIGSEGV
+@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_check():
with pytest.raises(subprocess.CalledProcessError):
ret = util.run(helper, 'abort', check=True)
+@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_leak():
with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'leak', valgrind=True)
+@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_undefined():
with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'undefined', valgrind=True)
+@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_undefined_branch():
with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'undefined_branch', valgrind=True)
+@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_read_after_free():
with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'read_after_free', valgrind=True)
+@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_write_after_free():
with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'write_after_free', valgrind=True)
diff --git a/tests/test_fuse.py b/tests/test_fuse.py
index 877fd64..c7608f4 100644
--- a/tests/test_fuse.py
+++ b/tests/test_fuse.py
@@ -2,14 +2,25 @@
#
# Tests of the fuse mount functionality.
+import pytest
import os
import util
+pytestmark = pytest.mark.skipif(
+ not util.have_fuse(), reason="bcachefs not built with fuse support.")
+
def test_mount(bfuse):
bfuse.mount()
bfuse.unmount()
bfuse.verify()
+def test_remount(bfuse):
+ bfuse.mount()
+ bfuse.unmount()
+ bfuse.mount()
+ bfuse.unmount()
+ bfuse.verify()
+
def test_lostfound(bfuse):
bfuse.mount()
diff --git a/tests/util.py b/tests/util.py
index 18d6002..fd8efd4 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -4,6 +4,7 @@ import os
import pytest
import re
import subprocess
+import sys
import tempfile
import threading
import time
@@ -15,6 +16,8 @@ BCH_PATH = DIR / 'bcachefs'
VPAT = re.compile(r'ERROR SUMMARY: (\d+) errors from (\d+) contexts')
+ENABLE_VALGRIND = os.getenv('BCACHEFS_TEST_USE_VALGRIND', 'yes') == 'yes'
+
class ValgrindFailedError(Exception):
def __init__(self, log):
self.log = log
@@ -36,6 +39,7 @@ def run(cmd, *args, valgrind=False, check=False):
ValgrindFailedError if there's a problem.
"""
cmds = [cmd] + list(args)
+ valgrind = valgrind and ENABLE_VALGRIND
if valgrind:
vout = tempfile.NamedTemporaryFile()
@@ -123,7 +127,7 @@ class FuseError(Exception):
def __init__(self, msg):
self.msg = msg
-class BFuse(threading.Thread):
+class BFuse:
'''bcachefs fuse runner.
This class runs bcachefs in fusemount mode, and waits until the mount has
@@ -133,7 +137,7 @@ class BFuse(threading.Thread):
'''
def __init__(self, dev, mnt):
- threading.Thread.__init__(self)
+ self.thread = None
self.dev = dev
self.mnt = mnt
self.ready = threading.Event()
@@ -146,12 +150,17 @@ class BFuse(threading.Thread):
def run(self):
"""Background thread which runs "bcachefs fusemount" under valgrind"""
- vout = tempfile.NamedTemporaryFile()
- cmd = [ 'valgrind',
- '--leak-check=full',
- '--log-file={}'.format(vout.name),
- BCH_PATH,
- 'fusemount', '-f', self.dev, self.mnt]
+ vout = None
+ cmd = []
+
+ if ENABLE_VALGRIND:
+ vout = tempfile.NamedTemporaryFile()
+ cmd += [ 'valgrind',
+ '--leak-check=full',
+ '--log-file={}'.format(vout.name) ]
+
+ cmd += [ BCH_PATH,
+ 'fusemount', '-f', self.dev, self.mnt]
print("Running {}".format(cmd))
@@ -188,7 +197,11 @@ class BFuse(threading.Thread):
def mount(self):
print("Starting fuse thread.")
- self.start()
+
+ assert not self.thread
+ self.thread = threading.Thread(target=self.run)
+ self.thread.start()
+
self.ready.wait()
print("Fuse is mounted.")
@@ -197,14 +210,22 @@ class BFuse(threading.Thread):
run("fusermount3", "-zu", self.mnt)
print("Waiting for thread to exit.")
- self.join(timeout)
- if self.isAlive():
+ self.thread.join(timeout)
+ if self.thread.is_alive():
self.proc.kill()
- self.join()
+ self.thread.join()
- check_valgrind(self.vout)
+ self.thread = None
+ self.ready.clear()
+
+ if self.vout:
+ check_valgrind(self.vout)
def verify(self):
assert self.returncode == 0
assert len(self.stdout) > 0
assert len(self.stderr) == 0
+
+def have_fuse():
+ res = run(BCH_PATH, 'fusemount', valgrind=False)
+ return "Please supply a mountpoint." in res.stdout