hanwen / go-fuse

FUSE bindings for Go
Other
2.04k stars 327 forks source link

Fails xfstests generic/013, renames files to ".deleted" #99

Closed rfjakob closed 8 years ago

rfjakob commented 8 years ago

I don't know why I haven't seen this earlier in my gocryptfs testing, but the hard link tracking (clientInodes) in pathfs seems to have a few issues (test case below). pathfs seems to lose track of linked files, internally renaming them to ".deleted". These files show up in directory listing but cannot be deleted nor stat'ed. Sometimes it crashes with a null pointer dereference in pathfs.

I am working on fixing the issues. It is not ready for merging yet, but it's probably going be a bigger patch. If you already want to take a look, the state right now with lots of added debugging code is here: https://github.com/rfjakob/go-fuse/commit/fd910e744f38180a9456a2086681ed3e5b60de52

Test case, with gocryptfs mounted on /tmp/b:

( set -e;
  while true; do
  ~/src/fuse-xfstests/ltp/fsstress -p 1 -z -f rmdir=10 -f link=10 -f creat=10 -f mkdir=10 -f rename=30 -f stat=30 -f unlink=30 -f truncate=20 -m 8 -n 1000 -d /tmp/b
  rm -R /tmp/b/*
  sleep 1
done )
hanwen commented 8 years ago

If something shows up in directory listings, then you must have somehow got these into the OpenDir() result.

can you post the stack trace for the NPE ?

rfjakob commented 8 years ago

Sorry, my description was unclear:

The files show up under their normal name, but gocryptfs gets passed ".deleted" on any operation, hence stat and everything else fails.

Will post the NPE sunday evening!

rfjakob commented 8 years ago

I cannot reproduce the NPE with a fresh checkout of go-fuse. Must have been caused by my debug code.

On the plus side, I can reproduce this with the loopback example (with ClientInodes enabled, patch: https://github.com/rfjakob/go-fuse/commit/1f50fb4dd13aa46eb282271662b6166c42417ed9 , otherwise no changes)

$ ( set -e; while true; do ~/src/fuse-xfstests/ltp/fsstress -p 1 -z -f rmdir=10 -f link=10 -f creat=10 -f mkdir=10 -f rename=30 -f stat=30 -f unlink=30 -f truncate=20 -m 8 -n 1000 -d /tmp/b; rm -R /tmp/b/*; sleep 1; done )
seed = 1456229227
rm: cannot remove ‘/tmp/b/p0/d9/d2c/d6c/dbc/d130/d12d/d156/d15a/d13b/f162’: No such file or directory
rm: cannot remove ‘/tmp/b/p0/d9/d2c/d6c/dbc/d130/d12d/d156/d15a/d13b’: Directory not empty

By the way, fsstress is the one included in xfstests, you can clone it from https://github.com/rfjakob/fuse-xfstests/tree/gocryptfs/ltp .

rfjakob commented 8 years ago

Found a single-shot reproducer that works every time. Note that the "sleep 1" in the middle is essential and the test comes back clean without it.

~/src/fuse-xfstests/ltp/fsstress -p 1 -z -f rmdir=10 -f link=10 -f creat=10 -f mkdir=10 -f rename=30 -f stat=30 -f unlink=30 -f truncate=20 -m 8 -n 1000 -d /tmp/b -s 1456162204 ; sleep 1; rm -Rf /tmp/b/*