Merge commit '780de81b36'

This commit is contained in:
Kent Overstreet 2019-11-28 15:08:27 -05:00
commit ffced87f08
7 changed files with 96 additions and 14 deletions

34
INSTALL
View File

@ -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

View File

@ -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))

View File

@ -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();

View File

@ -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 */

View File

@ -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)

View File

@ -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()

View File

@ -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