diff options
author | Jakob Unterwurzacher | 2020-04-19 21:57:53 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2020-04-19 22:00:56 +0200 |
commit | 9f9d59ded94f648202505e278f67667879e60be8 (patch) | |
tree | 17e9190c4aa752feab71545a56f0686b2ea64237 /internal/inomap/inomap_test.go | |
parent | fcdeb52390b15b0d59015dbd238835b9a6f6b3ff (diff) |
inomap: rework logic to efficiently support flags
Adding flags allows to use inomap in reverse mode,
replacing the clunky inoBaseDirIV/inoBaseNameFile
logic that causes problems with high underlying
inode numbers ( https://github.com/rfjakob/gocryptfs/issues/457 )
Microbenchmarks (values below) show that the "SingleDev"
case is now much slower due to an extra map lookup,
but this has no visible effects in ./test.bash results,
so there was no time spent optimizing the case further.
$ go test -bench=.
goos: linux
goarch: amd64
pkg: github.com/rfjakob/gocryptfs/internal/inomap
BenchmarkTranslateSingleDev-4 18757510 61.5 ns/op
BenchmarkTranslateManyDevs-4 18061515 64.5 ns/op
PASS
ok github.com/rfjakob/gocryptfs/internal/inomap 2.467s
Diffstat (limited to 'internal/inomap/inomap_test.go')
-rw-r--r-- | internal/inomap/inomap_test.go | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/internal/inomap/inomap_test.go b/internal/inomap/inomap_test.go index 0349fd6..8efc960 100644 --- a/internal/inomap/inomap_test.go +++ b/internal/inomap/inomap_test.go @@ -6,17 +6,15 @@ import ( ) func TestTranslate(t *testing.T) { - const baseDev = 12345 - m := New(baseDev) - - q := QIno{Dev: baseDev, Ino: 1} + m := New() + q := QIno{Ino: 1} out := m.Translate(q) if out != 1 { t.Errorf("expected 1, got %d", out) } - q.Ino = inumTranslateBase + q.Ino = maxPassthruIno out = m.Translate(q) - if out < inumTranslateBase { + if out < maxPassthruIno { t.Errorf("got %d", out) } out2 := m.Translate(q) @@ -27,61 +25,106 @@ func TestTranslate(t *testing.T) { func TestTranslateStress(t *testing.T) { const baseDev = 12345 - m := New(baseDev) + m := New() + + // Make sure baseDev gets namespace id zero + var q QIno + q.Dev = baseDev + m.Translate(q) + var wg sync.WaitGroup wg.Add(4) go func() { - q := QIno{Dev: baseDev} + // Some normal inode numbers on baseDev + var q QIno + q.Dev = baseDev for i := uint64(1); i <= 10000; i++ { q.Ino = i out := m.Translate(q) if out != i { - t.Fail() + t.Errorf("i=%d out=%d", i, out) + break } } wg.Done() }() go func() { - q := QIno{Dev: baseDev} + // Very high (>maxPassthruIno) inode numbers on baseDev + var q QIno + q.Dev = baseDev for i := uint64(1); i <= 10000; i++ { - q.Ino = inumTranslateBase + i + q.Ino = maxPassthruIno + i out := m.Translate(q) - if out < inumTranslateBase { - t.Fail() + if out < maxPassthruIno { + t.Errorf("out=%d", out) + break } } wg.Done() }() go func() { - q := QIno{Dev: 9999999} + // Device 9999999 + var q QIno + q.Dev = 9999999 for i := uint64(1); i <= 10000; i++ { q.Ino = i out := m.Translate(q) - if out < inumTranslateBase { - t.Fail() + if out < maxPassthruIno { + t.Errorf("out=%d", out) + break } } wg.Done() }() go func() { - q := QIno{Dev: 4444444} + // Device 4444444 + var q QIno + q.Dev = 4444444 for i := uint64(1); i <= 10000; i++ { q.Ino = i out := m.Translate(q) - if out < inumTranslateBase { - t.Fail() + if out < maxPassthruIno { + t.Errorf("out=%d", out) + break } } wg.Done() }() wg.Wait() - if m.Count() != 30000 { - t.Fail() + if len(m.spillMap) != 10000 { + t.Errorf("len=%d", len(m.spillMap)) + } + if len(m.namespaceMap) != 3 { + t.Errorf("len=%d", len(m.namespaceMap)) + } +} + +// TestUniqueness checks that unique (Dev, Flags, Ino) tuples get unique inode +// numbers +func TestUniqueness(t *testing.T) { + m := New() + var q QIno + outMap := make(map[uint64]struct{}) + for q.Dev = 0; q.Dev < 10; q.Dev++ { + for q.Flags = 0; q.Flags < 10; q.Flags++ { + // some go into spill + for q.Ino = maxPassthruIno - 100; q.Ino < maxPassthruIno+100; q.Ino++ { + out := m.Translate(q) + _, found := outMap[out] + if found { + t.Fatalf("inode number %d already used", out) + } + outMap[out] = struct{}{} + } + } + } + if len(outMap) != 10*10*200 { + t.Errorf("%d", len(outMap)) } } func BenchmarkTranslateSingleDev(b *testing.B) { - m := New(0) + m := New() var q QIno for n := 0; n < b.N; n++ { q.Ino = uint64(n % 1000) @@ -90,7 +133,7 @@ func BenchmarkTranslateSingleDev(b *testing.B) { } func BenchmarkTranslateManyDevs(b *testing.B) { - m := New(0) + m := New() var q QIno for n := 0; n < b.N; n++ { q.Dev = uint64(n % 10) |