inomap: split into separate package
inomap will also be used by fusefrontend_reverse in the future. Split if off openfiletable to make it independent.
This commit is contained in:
parent
194030f18a
commit
488111ce39
@ -17,6 +17,7 @@ import (
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
||||
"github.com/rfjakob/gocryptfs/internal/inomap"
|
||||
"github.com/rfjakob/gocryptfs/internal/openfiletable"
|
||||
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
|
||||
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
||||
@ -42,7 +43,7 @@ type File struct {
|
||||
// Content encryption helper
|
||||
contentEnc *contentenc.ContentEnc
|
||||
// Device and inode number uniquely identify the backing file
|
||||
qIno openfiletable.QIno
|
||||
qIno inomap.QIno
|
||||
// Entry in the open file table
|
||||
fileTableEntry *openfiletable.Entry
|
||||
// Store where the last byte was written
|
||||
@ -66,7 +67,7 @@ func NewFile(fd *os.File, fs *FS) (*File, fuse.Status) {
|
||||
tlog.Warn.Printf("NewFile: Fstat on fd %d failed: %v\n", fd.Fd(), err)
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
qi := openfiletable.QInoFromStat(&st)
|
||||
qi := inomap.QInoFromStat(&st)
|
||||
e := openfiletable.Register(qi)
|
||||
|
||||
return &File{
|
||||
@ -462,7 +463,7 @@ func (f *File) GetAttr(a *fuse.Attr) fuse.Status {
|
||||
if err != nil {
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
f.fs.inumMap.TranslateStat(&st)
|
||||
f.fs.inoMap.TranslateStat(&st)
|
||||
a.FromStat(&st)
|
||||
a.Size = f.contentEnc.CipherSizeToPlainSize(a.Size)
|
||||
if f.fs.args.ForceOwner != nil {
|
||||
|
@ -18,8 +18,8 @@ import (
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
||||
"github.com/rfjakob/gocryptfs/internal/inomap"
|
||||
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||
"github.com/rfjakob/gocryptfs/internal/openfiletable"
|
||||
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
|
||||
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
@ -59,9 +59,9 @@ type FS struct {
|
||||
IsIdle uint32
|
||||
// dirCache caches directory fds
|
||||
dirCache dirCacheStruct
|
||||
// inumMap translates inode numbers from different devices to unique inode
|
||||
// inoMap translates inode numbers from different devices to unique inode
|
||||
// numbers.
|
||||
inumMap *openfiletable.InumMap
|
||||
inoMap *inomap.InoMap
|
||||
}
|
||||
|
||||
//var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented.
|
||||
@ -85,7 +85,7 @@ func NewFS(args Args, c *contentenc.ContentEnc, n nametransform.NameTransformer)
|
||||
args: args,
|
||||
nameTransform: n,
|
||||
contentEnc: c,
|
||||
inumMap: openfiletable.NewInumMap(uint64(st.Dev)), // cast is needed for Darwin
|
||||
inoMap: inomap.New(uint64(st.Dev)), // cast is needed for Darwin
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ func (fs *FS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.S
|
||||
}
|
||||
a := &fuse.Attr{}
|
||||
st2 := syscallcompat.Unix2syscall(st)
|
||||
fs.inumMap.TranslateStat(&st2)
|
||||
fs.inoMap.TranslateStat(&st2)
|
||||
a.FromStat(&st2)
|
||||
if a.IsRegular() {
|
||||
a.Size = fs.contentEnc.CipherSizeToPlainSize(a.Size)
|
||||
|
@ -1,4 +1,4 @@
|
||||
package openfiletable
|
||||
package inomap
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@ -8,25 +8,25 @@ import (
|
||||
// UINT64_MAX = 18446744073709551615
|
||||
const inumTranslateBase = 10000000000000000000
|
||||
|
||||
// InumMap ... see NewInumMap() for description.
|
||||
type InumMap struct {
|
||||
// InoMap ... see New() for description.
|
||||
type InoMap struct {
|
||||
sync.Mutex
|
||||
baseDev uint64
|
||||
translate map[QIno]uint64
|
||||
translateNext uint64
|
||||
}
|
||||
|
||||
// NewInumMap returns a new inumMap.
|
||||
// New returns a new InoMap.
|
||||
//
|
||||
// inumMap translates (device uint64, inode uint64) pairs to unique uint64
|
||||
// InoMap translates (device uint64, inode uint64) pairs to unique uint64
|
||||
// inode numbers.
|
||||
// Inode numbers on the "baseDev" are passed through unchanged (as long as they
|
||||
// are not higher than inumTranslateBase).
|
||||
// Inode numbers on other devices are remapped to the number space above
|
||||
// 10000000000000000000. The mapping is stored in a simple Go map. Entries
|
||||
// can only be added and are never removed.
|
||||
func NewInumMap(baseDev uint64) *InumMap {
|
||||
return &InumMap{
|
||||
func New(baseDev uint64) *InoMap {
|
||||
return &InoMap{
|
||||
baseDev: baseDev,
|
||||
translate: make(map[QIno]uint64),
|
||||
translateNext: inumTranslateBase,
|
||||
@ -34,7 +34,7 @@ func NewInumMap(baseDev uint64) *InumMap {
|
||||
}
|
||||
|
||||
// Translate maps the passed-in (device, inode) pair to a unique inode number.
|
||||
func (m *InumMap) Translate(in QIno) (out uint64) {
|
||||
func (m *InoMap) Translate(in QIno) (out uint64) {
|
||||
if in.Dev == m.baseDev && in.Ino < inumTranslateBase {
|
||||
return in.Ino
|
||||
}
|
||||
@ -52,12 +52,12 @@ func (m *InumMap) Translate(in QIno) (out uint64) {
|
||||
|
||||
// TranslateStat translates the inode number contained in "st" if neccessary.
|
||||
// Convience wrapper around Translate().
|
||||
func (m *InumMap) TranslateStat(st *syscall.Stat_t) {
|
||||
func (m *InoMap) TranslateStat(st *syscall.Stat_t) {
|
||||
in := QInoFromStat(st)
|
||||
st.Ino = m.Translate(in)
|
||||
}
|
||||
|
||||
// Count returns the number of entries in the translation table.
|
||||
func (m *InumMap) Count() int {
|
||||
func (m *InoMap) Count() int {
|
||||
return len(m.translate)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package openfiletable
|
||||
package inomap
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@ -7,7 +7,7 @@ import (
|
||||
|
||||
func TestTranslate(t *testing.T) {
|
||||
const baseDev = 12345
|
||||
m := NewInumMap(baseDev)
|
||||
m := New(baseDev)
|
||||
|
||||
q := QIno{Dev: baseDev, Ino: 1}
|
||||
out := m.Translate(q)
|
||||
@ -27,7 +27,7 @@ func TestTranslate(t *testing.T) {
|
||||
|
||||
func TestTranslateStress(t *testing.T) {
|
||||
const baseDev = 12345
|
||||
m := NewInumMap(baseDev)
|
||||
m := New(baseDev)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(4)
|
||||
go func() {
|
25
internal/inomap/qino.go
Normal file
25
internal/inomap/qino.go
Normal file
@ -0,0 +1,25 @@
|
||||
package inomap
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// QIno = Qualified Inode number.
|
||||
// Uniquely identifies a backing file through the device number,
|
||||
// inode number pair.
|
||||
type QIno struct {
|
||||
// Stat_t.{Dev,Ino} is uint64 on 32- and 64-bit Linux
|
||||
Dev uint64
|
||||
Ino uint64
|
||||
}
|
||||
|
||||
// QInoFromStat fills a new QIno struct with the passed Stat_t info.
|
||||
func QInoFromStat(st *syscall.Stat_t) QIno {
|
||||
return QIno{
|
||||
// There are some architectures that use 32-bit values here
|
||||
// (darwin, freebsd-32, maybe others). Add and explicit cast to make
|
||||
// this function work everywhere.
|
||||
Dev: uint64(st.Dev),
|
||||
Ino: uint64(st.Ino),
|
||||
}
|
||||
}
|
@ -7,29 +7,10 @@ package openfiletable
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/inomap"
|
||||
)
|
||||
|
||||
// QIno = Qualified Inode number.
|
||||
// Uniquely identifies a backing file through the device number,
|
||||
// inode number pair.
|
||||
type QIno struct {
|
||||
// Stat_t.{Dev,Ino} is uint64 on 32- and 64-bit Linux
|
||||
Dev uint64
|
||||
Ino uint64
|
||||
}
|
||||
|
||||
// QInoFromStat fills a new QIno struct with the passed Stat_t info.
|
||||
func QInoFromStat(st *syscall.Stat_t) QIno {
|
||||
return QIno{
|
||||
// There are some architectures that use 32-bit values here
|
||||
// (darwin, freebsd-32, maybe others). Add and explicit cast to make
|
||||
// this function work everywhere.
|
||||
Dev: uint64(st.Dev),
|
||||
Ino: uint64(st.Ino),
|
||||
}
|
||||
}
|
||||
|
||||
// wlock - serializes write accesses to each file (identified by inode number)
|
||||
// Writing partial blocks means we have to do read-modify-write cycles. We
|
||||
// really don't want concurrent writes there.
|
||||
@ -38,7 +19,7 @@ func QInoFromStat(st *syscall.Stat_t) QIno {
|
||||
var t table
|
||||
|
||||
func init() {
|
||||
t.entries = make(map[QIno]*Entry)
|
||||
t.entries = make(map[inomap.QIno]*Entry)
|
||||
}
|
||||
|
||||
type table struct {
|
||||
@ -52,7 +33,7 @@ type table struct {
|
||||
// Protects map access
|
||||
sync.Mutex
|
||||
// Table entries
|
||||
entries map[QIno]*Entry
|
||||
entries map[inomap.QIno]*Entry
|
||||
}
|
||||
|
||||
// Entry is an entry in the open file table
|
||||
@ -71,7 +52,7 @@ type Entry struct {
|
||||
|
||||
// Register creates an open file table entry for "qi" (or incrementes the
|
||||
// reference count if the entry already exists) and returns the entry.
|
||||
func Register(qi QIno) *Entry {
|
||||
func Register(qi inomap.QIno) *Entry {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
@ -86,7 +67,7 @@ func Register(qi QIno) *Entry {
|
||||
|
||||
// Unregister decrements the reference count for "qi" and deletes the entry from
|
||||
// the open file table if the reference count reaches 0.
|
||||
func Unregister(qi QIno) {
|
||||
func Unregister(qi inomap.QIno) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user