aboutsummaryrefslogtreecommitdiff
path: root/internal/inomap/inomap_test.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2020-04-19 21:57:53 +0200
committerJakob Unterwurzacher2020-04-19 22:00:56 +0200
commit9f9d59ded94f648202505e278f67667879e60be8 (patch)
tree17e9190c4aa752feab71545a56f0686b2ea64237 /internal/inomap/inomap_test.go
parentfcdeb52390b15b0d59015dbd238835b9a6f6b3ff (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.go89
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)