[Bug 196726] fusefs truncates files on read, sometimes returns wrong data.

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Wed Jan 14 14:59:48 UTC 2015


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=196726

            Bug ID: 196726
           Summary: fusefs truncates files on read, sometimes returns
                    wrong data.
           Product: Base System
           Version: 10.1-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: freebsd-stable at z42.net

I made a python program to tickle two fusefs problems that may well be the same
problem in different forms, both loosing data. I assume the problem is in the
kernel and not the library, but have not verified this. (I have only looked at
the symptoms.)

#!/usr/bin/env python
#
# FreeBSD (10.1-RELEASE) fuse seems pretty buggy.
# File attributes are cached forever (not tested here), and reported size
# is enforced. (So appending to a file outside the fuse layer has no effect
# if the file is already seen.) And even worse, the first time a file is
# closed (even ro) the reported size is truncated to. This updates the
# mtime, and of course risks discarding data written from somewhere else.
# (This is in test1.)
#
# File contents are also sometimes wrong in surprising ways when a file is
# overwritten. (This is in test2.)
#
# This program takes two directories as arguments, the first one a normal
# mount and the second a fuse mount (e.g. fusexmp or sshfs) of the same dir.

def test2(normal_dir, fuse_dir, test_fn):
    from os.path import exists, isdir, join
    assert isdir(normal_dir)
    assert isdir(fuse_dir)
    assert not exists(join(normal_dir, test_fn))
    assert not exists(join(fuse_dir, test_fn))

    with open(join(normal_dir, test_fn), "wb") as fh: 
        fh.write("foo")

    with open(join(fuse_dir, test_fn), "rb") as fh: 
        assert fh.read() == "foo", "this should work"

    with open(join(normal_dir, test_fn), "wb") as fh: 
        fh.write("longer")

    with open(join(fuse_dir, test_fn), "rb") as fh: 
        data = fh.read()
        assert data == "longer", "fuse misread %s ('longer' != %r)" % (test_fn,
data,)

def test1(normal_dir, fuse_dir, test_fn):
    from os.path import exists, isdir, join
    assert isdir(normal_dir)
    assert isdir(fuse_dir)
    assert not exists(join(normal_dir, test_fn))

    with open(join(normal_dir, test_fn), "wb") as normal_fh:
        normal_fh.write("foo")
        normal_fh.flush()
        with open(join(fuse_dir, test_fn), "rb") as fuse_fh:
            assert fuse_fh.read() == "foo", "this should work"
            normal_fh.write("bar")
            normal_fh.flush()
    with open(join(normal_dir, test_fn), "rb") as normal_fh:
        data = normal_fh.read()
        assert data == "foobar", "fuse truncated %s ('foobar' != %r)" %
(test_fn, data,)

if __name__ == "__main__":
    from sys import argv
    from traceback import print_exc

    normal_dir, fuse_dir = argv[1:]
    try:
        test1(normal_dir, fuse_dir, "TEST1")
    except Exception:
        print "Test 1 failed:"
        print_exc()

    try:
        test2(normal_dir, fuse_dir, "TEST2")
    except Exception:
        print "Test 2 failed:"
        print_exc()

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list