Skip to content

Commit

Permalink
inomap: deterministically set root device
Browse files Browse the repository at this point in the history
We used to have "first Translate() wins". This is not deterministic,
as the LOOKUP for the root directory does not seem to reach us, so
the first user LOOKUP would win, which may be on a mountpoint.
  • Loading branch information
rfjakob committed Sep 10, 2021
1 parent ee56103 commit c9b825c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 20 deletions.
12 changes: 11 additions & 1 deletion internal/fusefrontend/root_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,28 @@ type RootNode struct {
}

func NewRootNode(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
var rootDev uint64
var st syscall.Stat_t
if err := syscall.Stat(args.Cipherdir, &st); err != nil {
tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
} else {
rootDev = uint64(st.Dev)
}

if len(args.Exclude) > 0 {
tlog.Warn.Printf("Forward mode does not support -exclude")
}

ivLen := nametransform.DirIVLen
if args.PlaintextNames {
ivLen = 0
}

rn := &RootNode{
args: args,
nameTransform: n,
contentEnc: c,
inoMap: inomap.New(),
inoMap: inomap.New(rootDev),
dirCache: dirCache{ivLen: ivLen},
quirks: syscallcompat.DetectQuirks(args.Cipherdir),
}
Expand Down
17 changes: 11 additions & 6 deletions internal/fusefrontend_reverse/root_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package fusefrontend_reverse

import (
"log"
"os"
"path/filepath"
"strings"
"syscall"

"github.com/rfjakob/gocryptfs/v2/internal/exitcodes"

"github.com/rfjakob/gocryptfs/v2/internal/tlog"

"golang.org/x/sys/unix"
Expand Down Expand Up @@ -46,20 +49,22 @@ type RootNode struct {
// ReverseFS provides an encrypted view.
func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
var rootDev uint64
if args.OneFileSystem {
var st syscall.Stat_t
err := syscall.Stat(args.Cipherdir, &st)
if err != nil {
log.Panicf("Could not stat backing directory %q: %v", args.Cipherdir, err)
var st syscall.Stat_t
if err := syscall.Stat(args.Cipherdir, &st); err != nil {
tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
if args.OneFileSystem {
tlog.Fatal.Printf("This is a fatal error in combination with -one-file-system")
os.Exit(exitcodes.CipherDir)
}
} else {
rootDev = uint64(st.Dev)
}

rn := &RootNode{
args: args,
nameTransform: n,
contentEnc: c,
inoMap: inomap.New(),
inoMap: inomap.New(rootDev),
rootDev: rootDev,
}
if len(args.Exclude) > 0 || len(args.ExcludeWildcard) > 0 || len(args.ExcludeFrom) > 0 {
Expand Down
13 changes: 11 additions & 2 deletions internal/inomap/inomap.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,22 @@ type InoMap struct {
}

// New returns a new InoMap.
func New() *InoMap {
return &InoMap{
// Inode numbers on device `rootDev` will be passed through as-is.
// If `rootDev` is zero, the first Translate() call decides the effective
// rootDev.
func New(rootDev uint64) *InoMap {
m := &InoMap{
namespaceMap: make(map[namespaceData]uint16),
namespaceNext: 0,
spillMap: make(map[QIno]uint64),
spillNext: 0,
}
if rootDev > 0 {
// Reserve namespace 0 for rootDev
m.namespaceMap[namespaceData{rootDev, 0}] = 0
m.namespaceNext = 1
}
return m
}

var spillWarn sync.Once
Expand Down
17 changes: 6 additions & 11 deletions internal/inomap/inomap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

func TestTranslate(t *testing.T) {
m := New()
m := New(0)
q := QIno{Ino: 1}
out := m.Translate(q)
if out != 1 {
Expand All @@ -25,12 +25,7 @@ func TestTranslate(t *testing.T) {

func TestTranslateStress(t *testing.T) {
const baseDev = 12345
m := New()

// Make sure baseDev gets namespace id zero
var q QIno
q.Dev = baseDev
m.Translate(q)
m := New(baseDev)

var wg sync.WaitGroup
wg.Add(4)
Expand Down Expand Up @@ -100,7 +95,7 @@ func TestTranslateStress(t *testing.T) {
}

func TestSpill(t *testing.T) {
m := New()
m := New(0)
var q QIno
q.Ino = maxPassthruIno + 1
out1 := m.Translate(q)
Expand All @@ -119,7 +114,7 @@ func TestSpill(t *testing.T) {
// TestUniqueness checks that unique (Dev, Flags, Ino) tuples get unique inode
// numbers
func TestUniqueness(t *testing.T) {
m := New()
m := New(0)
var q QIno
outMap := make(map[uint64]struct{})
for q.Dev = 0; q.Dev < 10; q.Dev++ {
Expand All @@ -141,7 +136,7 @@ func TestUniqueness(t *testing.T) {
}

func BenchmarkTranslateSingleDev(b *testing.B) {
m := New()
m := New(0)
var q QIno
for n := 0; n < b.N; n++ {
q.Ino = uint64(n % 1000)
Expand All @@ -150,7 +145,7 @@ func BenchmarkTranslateSingleDev(b *testing.B) {
}

func BenchmarkTranslateManyDevs(b *testing.B) {
m := New()
m := New(0)
var q QIno
for n := 0; n < b.N; n++ {
q.Dev = uint64(n % 10)
Expand Down

0 comments on commit c9b825c

Please sign in to comment.