fsmount.go 3.24 KB
Newer Older
1
package fuse
2

3
import (
4
	"log"
5 6
	"sync"
	"unsafe"
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
7

8
	"github.com/hanwen/go-fuse/raw"
9
)
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
10

11
var _ = log.Println
12 13 14

// openedFile stores either an open dir or an open file.
type openedFile struct {
15
	handled
16

17
	WithFlags
18

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
19
	dir rawDir
20 21 22 23
}

type fileSystemMount struct {
	// The file system we mounted here.
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
24
	fs NodeFileSystem
25 26

	// Node that we were mounted on.
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
27
	mountInode *Inode
28

29 30 31
	// Parent to the mountInode.
	parentInode *Inode

32 33 34 35
	// Options for the mount.
	options *FileSystemOptions

	// Protects Children hashmaps within the mount.  treeLock
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
36
	// should be acquired before openFilesLock.
37 38 39
	//
	// If multiple treeLocks must be acquired, the treeLocks
	// closer to the root must be acquired first.
40 41 42
	treeLock sync.RWMutex

	// Manage filehandles of open files.
43
	openFiles handleMap
44

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
45
	Debug bool
46 47

	connector *FileSystemConnector
48 49
}

50
// Must called with lock for parent held.
51
func (m *fileSystemMount) mountName() string {
52 53
	for k, v := range m.parentInode.children {
		if m.mountInode == v {
54 55 56 57 58 59 60
			return k
		}
	}
	panic("not found")
	return ""
}

61 62 63
func (m *fileSystemMount) setOwner(attr *raw.Attr) {
	if m.options.Owner != nil {
		attr.Owner = *(*raw.Owner)(m.options.Owner)
64 65
	}
}
66

67
func (m *fileSystemMount) fillEntry(out *raw.EntryOut) {
68 69 70
	splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec)
	splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
	m.setOwner(&out.Attr)
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
71
	if out.Mode&S_IFDIR == 0 && out.Nlink == 0 {
72
		out.Nlink = 1
73 74
	}
}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
75

76
func (m *fileSystemMount) fillAttr(out *raw.AttrOut, nodeId uint64) {
77 78
	splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
	m.setOwner(&out.Attr)
79
	out.Ino = nodeId
80 81
}

82 83
func (m *fileSystemMount) getOpenedFile(h uint64) *openedFile {
	b := (*openedFile)(unsafe.Pointer(m.openFiles.Decode(h)))
84
	if m.connector.debug && b.WithFlags.Description != "" {
85
		log.Printf("File %d = %q", h, b.WithFlags.Description)
86
	}
87 88 89
	return b
}

90
func (m *fileSystemMount) unregisterFileHandle(handle uint64, node *Inode) *openedFile {
91
	_, obj := m.openFiles.Forget(handle, 1)
92
	opened := (*openedFile)(unsafe.Pointer(obj))
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
93
	node.openFilesMutex.Lock()
94
	idx := -1
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
95
	for i, v := range node.openFiles {
96 97 98 99 100 101
		if v == opened {
			idx = i
			break
		}
	}

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
102 103 104
	l := len(node.openFiles)
	node.openFiles[idx] = node.openFiles[l-1]
	node.openFiles = node.openFiles[:l-1]
105
	node.openFilesMutex.Unlock()
106 107 108 109

	return opened
}

110
func (m *fileSystemMount) registerFileHandle(node *Inode, dir rawDir, f File, flags uint32) (uint64, *openedFile) {
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
111
	node.openFilesMutex.Lock()
112
	b := &openedFile{
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
113
		dir: dir,
114
		WithFlags: WithFlags{
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
115
			File:      f,
116 117
			OpenFlags: flags,
		},
118
	}
119 120 121 122 123 124 125

	for {
		withFlags, ok := f.(*WithFlags)
		if !ok {
			break
		}

Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
126
		b.WithFlags.File = withFlags.File
127 128 129
		b.WithFlags.FuseFlags |= withFlags.FuseFlags
		b.WithFlags.Description += withFlags.Description
		f = withFlags.File
130 131
	}

132 133 134
	if b.WithFlags.File != nil {
		b.WithFlags.File.SetInode(node)
	}
Han-Wen Nienhuys's avatar
Han-Wen Nienhuys committed
135
	node.openFiles = append(node.openFiles, b)
136
	handle := m.openFiles.Register(&b.handled)
137
	node.openFilesMutex.Unlock()
138 139
	return handle, b
}
140 141

// Creates a return entry for a non-existent path.
142
func (m *fileSystemMount) negativeEntry(out *raw.EntryOut) bool {
143
	if m.options.NegativeTimeout > 0.0 {
144
		out.NodeId = 0
145
		splitDuration(m.options.NegativeTimeout, &out.EntryValid, &out.EntryValidNsec)
146
		return true
147
	}
148
	return false
149
}