Commit 3b9d2f33 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Make clientInode support optional, and switch it off by default.

parent b04236ac
......@@ -11,6 +11,7 @@ import (
func main() {
version := flag.Bool("version", false, "print version number")
debug := flag.Bool("debug", false, "debug on")
hardlinks := flag.Bool("hardlinks", false, "support hardlinks")
delcache_ttl := flag.Float64("deletion_cache_ttl", 5.0, "Deletion cache TTL in seconds.")
branchcache_ttl := flag.Float64("branchcache_ttl", 5.0, "Branch cache TTL in seconds.")
deldirname := flag.String(
......@@ -41,9 +42,12 @@ func main() {
},
UpdateOnMount: true,
}
pathOptions := fuse.PathNodeFsOptions{
ClientInodes: *hardlinks,
}
gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options)
pathfs := fuse.NewPathNodeFs(gofs)
pathfs := fuse.NewPathNodeFs(gofs, &pathOptions)
state, conn, err := fuse.MountNodeFileSystem(flag.Arg(0), pathfs, nil)
if err != nil {
fmt.Printf("Mount fail: %v\n", err)
......
......@@ -37,8 +37,8 @@ func main() {
AttrTimeout: 1.0,
EntryTimeout: 1.0,
}
conn := fuse.NewFileSystemConnector(fuse.NewPathNodeFs(finalFs), opts)
pathFs := fuse.NewPathNodeFs(finalFs, nil)
conn := fuse.NewFileSystemConnector(pathFs, opts)
state := fuse.NewMountState(conn)
state.Debug = *debug
......
......@@ -35,7 +35,7 @@ func setupCacheTest() (string, *PathNodeFs, func()) {
fs := &cacheFs{
LoopbackFileSystem: NewLoopbackFileSystem(dir + "/orig"),
}
pfs := NewPathNodeFs(fs)
pfs := NewPathNodeFs(fs, nil)
state, conn, err := MountNodeFileSystem(dir+"/mnt", pfs, nil)
CheckSuccess(err)
state.Debug = true
......
......@@ -21,6 +21,6 @@ func MountNodeFileSystem(mountpoint string, nodeFs NodeFileSystem, opts *FileSys
}
func MountPathFileSystem(mountpoint string, pathFs FileSystem, opts *FileSystemOptions) (*MountState, *FileSystemConnector, os.Error) {
nfs := NewPathNodeFs(pathFs)
nfs := NewPathNodeFs(pathFs, nil)
return MountNodeFileSystem(mountpoint, nfs, opts)
}
......@@ -71,7 +71,8 @@ func NewTestCase(t *testing.T) *testCase {
pfs = NewLockingFileSystem(pfs)
var rfs RawFileSystem
me.pathFs = NewPathNodeFs(pfs)
me.pathFs = NewPathNodeFs(pfs, &PathNodeFsOptions{
ClientInodes: true})
me.connector = NewFileSystemConnector(me.pathFs,
&FileSystemOptions{
EntryTimeout: testTtl,
......
......@@ -35,7 +35,7 @@ func TestMountRename(t *testing.T) {
ts := NewTestCase(t)
defer ts.Cleanup()
fs := NewPathNodeFs(NewLoopbackFileSystem(ts.orig))
fs := NewPathNodeFs(NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil)
if !code.Ok() {
t.Fatal("mount should succeed")
......@@ -51,7 +51,7 @@ func TestMountReaddir(t *testing.T) {
ts := NewTestCase(t)
defer ts.Cleanup()
fs := NewPathNodeFs(NewLoopbackFileSystem(ts.orig))
fs := NewPathNodeFs(NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil)
if !code.Ok() {
t.Fatal("mount should succeed")
......@@ -72,7 +72,7 @@ func TestRecursiveMount(t *testing.T) {
err := ioutil.WriteFile(ts.orig+"/hello.txt", []byte("blabla"), 0644)
CheckSuccess(err)
fs := NewPathNodeFs(NewLoopbackFileSystem(ts.orig))
fs := NewPathNodeFs(NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil)
if !code.Ok() {
t.Fatal("mount should succeed")
......@@ -109,7 +109,7 @@ func TestDeletedUnmount(t *testing.T) {
defer ts.Cleanup()
submnt := filepath.Join(ts.mnt, "mnt")
pfs2 := NewPathNodeFs(NewLoopbackFileSystem(ts.orig))
pfs2 := NewPathNodeFs(NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", pfs2, nil)
if !code.Ok() {
t.Fatal("Mount error", code)
......
......@@ -53,7 +53,7 @@ func NewNotifyTest() *NotifyTest {
NegativeTimeout: entryTtl,
}
me.pathfs = NewPathNodeFs(me.fs)
me.pathfs = NewPathNodeFs(me.fs, nil)
me.state, me.connector, err = MountNodeFileSystem(me.dir, me.pathfs, opts)
CheckSuccess(err)
me.state.Debug = true
......
......@@ -37,6 +37,14 @@ type PathNodeFs struct {
// This map lists all the parent links known for a given
// nodeId.
clientInodeMap map[uint64][]*clientInodePath
options *PathNodeFsOptions
}
type PathNodeFsOptions struct {
// If ClientInodes is set, use Inode returned from GetAttr to
// find hard-linked files.
ClientInodes bool
}
func (me *PathNodeFs) Mount(path string, nodeFs NodeFileSystem, opts *FileSystemOptions) Status {
......@@ -139,14 +147,19 @@ func (me *PathNodeFs) AllFiles(name string, mask uint32) []WithFlags {
return n.Files(mask)
}
func NewPathNodeFs(fs FileSystem) *PathNodeFs {
func NewPathNodeFs(fs FileSystem, opts *PathNodeFsOptions) *PathNodeFs {
root := new(pathInode)
root.fs = fs
if opts == nil {
opts = &PathNodeFsOptions{}
}
me := &PathNodeFs{
fs: fs,
root: root,
clientInodeMap: map[uint64][]*clientInodePath{},
options: opts,
}
root.pathFs = me
return me
......@@ -224,7 +237,7 @@ func (me *pathInode) addChild(name string, child *pathInode) {
child.Parent = me
child.Name = name
if child.clientInode > 0 {
if child.clientInode > 0 && me.pathFs.options.ClientInodes {
defer me.LockTree()()
m := me.pathFs.clientInodeMap[child.clientInode]
e := &clientInodePath{
......@@ -242,7 +255,7 @@ func (me *pathInode) rmChild(name string) *pathInode {
}
ch := childInode.FsNode().(*pathInode)
if ch.clientInode > 0 {
if ch.clientInode > 0 && me.pathFs.options.ClientInodes {
defer me.LockTree()()
m := me.pathFs.clientInodeMap[ch.clientInode]
......@@ -275,7 +288,7 @@ func (me *pathInode) rmChild(name string) *pathInode {
// Handle a change in clientInode number for an other wise unchanged
// pathInode.
func (me *pathInode) setClientInode(ino uint64) {
if ino == me.clientInode {
if ino == me.clientInode || !me.pathFs.options.ClientInodes {
return
}
defer me.LockTree()()
......@@ -293,7 +306,7 @@ func (me *pathInode) setClientInode(ino uint64) {
}
func (me *pathInode) OnForget() {
if me.clientInode == 0 {
if me.clientInode == 0 || !me.pathFs.options.ClientInodes {
return
}
defer me.LockTree()()
......@@ -465,25 +478,29 @@ func (me *pathInode) Lookup(name string, context *Context) (fi *os.FileInfo, nod
fullPath := filepath.Join(me.GetPath(), name)
fi, code = me.fs.GetAttr(fullPath, context)
if code.Ok() {
node = me.findChild(fi.Ino, fi.IsDirectory(), name)
node = me.findChild(fi, name, fullPath)
}
return
}
func (me *pathInode) findChild(ino uint64, isDir bool, name string) (out *pathInode) {
if ino > 0 {
func (me *pathInode) findChild(fi *os.FileInfo, name string, fullPath string) (out *pathInode) {
if fi.Ino > 0 {
unlock := me.RLockTree()
v := me.pathFs.clientInodeMap[ino]
v := me.pathFs.clientInodeMap[fi.Ino]
if len(v) > 0 {
out = v[0].node
if fi.Nlink == 1 {
log.Println("Found linked inode, but Nlink == 1", fullPath)
}
}
unlock()
}
if out == nil {
out = me.createChild(isDir)
out.clientInode = ino
out = me.createChild(fi.IsDirectory())
out.clientInode = fi.Ino
me.addChild(name, out)
}
......
......@@ -110,7 +110,7 @@ func (me *AutoUnionFs) createFs(name string, roots []string) fuse.Status {
}
log.Printf("Adding workspace %v for roots %v", name, ufs.Name())
nfs := fuse.NewPathNodeFs(ufs)
nfs := fuse.NewPathNodeFs(ufs, nil)
code := me.nodeFs.Mount(name, nfs, &me.options.FileSystemOptions)
if code.Ok() {
me.knownFileSystems[name] = knownFs{
......
......@@ -54,7 +54,9 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
NegativeTimeout: .5 * entryTtl,
}
state, conn, err := fuse.MountPathFileSystem(wd+"/mount", ufs, opts)
pathfs := fuse.NewPathNodeFs(ufs,
&fuse.PathNodeFsOptions{ClientInodes: true})
state, conn, err := fuse.MountNodeFileSystem(wd+"/mount", pathfs, opts)
CheckSuccess(err)
conn.Debug = true
state.Debug = true
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment