Commit a27cac55 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys Committed by Han-Wen Nienhuys

Add Debug fields to all Options structs, and use those.

SetDebug methods are maintained for compatibility.

This is part of a patch series to process the INIT opcode on
mount. This will enable filesystems to switch functionality depending
on kernel settings.

In order to get the debug output for the INIT opcode, the debug option
must be passed to the mount method.

Deprecate the SetDebug methods. There is often little practical use in
toggling debug on the fly, since the error scenarios depend on timing
details, and must usually be isolated into unittests.

Change-Id: I221c995add5f7621b627f738d7e97af7daf81b2a
parent 61880caa
...@@ -31,7 +31,6 @@ func setupFs(fs pathfs.FileSystem) (string, func()) { ...@@ -31,7 +31,6 @@ func setupFs(fs pathfs.FileSystem) (string, func()) {
lmap := NewLatencyMap() lmap := NewLatencyMap()
state.RecordLatencies(lmap) state.RecordLatencies(lmap)
// state.SetDebug(true)
go state.Serve() go state.Serve()
return mountPoint, func() { return mountPoint, func() {
......
...@@ -43,6 +43,7 @@ func main() { ...@@ -43,6 +43,7 @@ func main() {
AttrTimeout: time.Second, AttrTimeout: time.Second,
NegativeTimeout: time.Second, NegativeTimeout: time.Second,
Owner: fuse.CurrentOwner(), Owner: fuse.CurrentOwner(),
Debug: *debug,
}, },
UpdateOnMount: true, UpdateOnMount: true,
PathNodeFsOptions: pathfs.PathNodeFsOptions{ PathNodeFsOptions: pathfs.PathNodeFsOptions{
...@@ -52,19 +53,18 @@ func main() { ...@@ -52,19 +53,18 @@ func main() {
} }
fsOpts := nodefs.Options{ fsOpts := nodefs.Options{
PortableInodes: *portableInodes, PortableInodes: *portableInodes,
Debug: *debug,
} }
gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options) gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options)
pathfs := pathfs.NewPathNodeFs(gofs, nil) pathfs := pathfs.NewPathNodeFs(gofs, &pathfs.PathNodeFsOptions{
state, conn, err := nodefs.MountRoot(flag.Arg(0), pathfs.Root(), &fsOpts) Debug: *debug,
})
state, _, err := nodefs.MountRoot(flag.Arg(0), pathfs.Root(), &fsOpts)
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
os.Exit(1) os.Exit(1)
} }
pathfs.SetDebug(*debug)
conn.SetDebug(*debug)
state.SetDebug(*debug)
state.Serve() state.Serve()
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
...@@ -82,13 +82,13 @@ func main() { ...@@ -82,13 +82,13 @@ func main() {
AllowOther: *other, AllowOther: *other,
Name: "loopbackfs", Name: "loopbackfs",
FsName: origAbs, FsName: origAbs,
Debug: *debug,
} }
state, err := fuse.NewServer(conn.RawFS(), mountPoint, mOpts) state, err := fuse.NewServer(conn.RawFS(), mountPoint, mOpts)
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
os.Exit(1) os.Exit(1)
} }
state.SetDebug(*debug)
fmt.Println("Mounted!") fmt.Println("Mounted!")
state.Serve() state.Serve()
......
...@@ -25,12 +25,13 @@ func main() { ...@@ -25,12 +25,13 @@ func main() {
prefix := flag.Arg(1) prefix := flag.Arg(1)
root := nodefs.NewMemNodeFSRoot(prefix) root := nodefs.NewMemNodeFSRoot(prefix)
conn := nodefs.NewFileSystemConnector(root, nil) conn := nodefs.NewFileSystemConnector(root, nil)
server, err := fuse.NewServer(conn.RawFS(), mountPoint, nil) server, err := fuse.NewServer(conn.RawFS(), mountPoint, &fuse.MountOptions{
Debug: *debug,
})
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
os.Exit(1) os.Exit(1)
} }
server.SetDebug(*debug)
fmt.Println("Mounted!") fmt.Println("Mounted!")
server.Serve() server.Serve()
} }
...@@ -23,12 +23,13 @@ func main() { ...@@ -23,12 +23,13 @@ func main() {
fs := zipfs.NewMultiZipFs() fs := zipfs.NewMultiZipFs()
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), nil) opts := nodefs.NewOptions()
opts.Debug = *debug
state, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), opts)
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
os.Exit(1) os.Exit(1)
} }
state.SetDebug(*debug)
state.Serve() state.Serve()
} }
...@@ -53,6 +53,7 @@ func main() { ...@@ -53,6 +53,7 @@ func main() {
opts := &nodefs.Options{ opts := &nodefs.Options{
AttrTimeout: time.Duration(*ttl * float64(time.Second)), AttrTimeout: time.Duration(*ttl * float64(time.Second)),
EntryTimeout: time.Duration(*ttl * float64(time.Second)), EntryTimeout: time.Duration(*ttl * float64(time.Second)),
Debug: *debug,
} }
state, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), opts) state, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), opts)
if err != nil { if err != nil {
...@@ -60,7 +61,6 @@ func main() { ...@@ -60,7 +61,6 @@ func main() {
os.Exit(1) os.Exit(1)
} }
state.SetDebug(*debug)
runtime.GC() runtime.GC()
if profFile != nil { if profFile != nil {
pprof.StartCPUProfile(profFile) pprof.StartCPUProfile(profFile)
......
...@@ -47,12 +47,12 @@ func main() { ...@@ -47,12 +47,12 @@ func main() {
AttrTimeout: time.Duration(*entry_ttl * float64(time.Second)), AttrTimeout: time.Duration(*entry_ttl * float64(time.Second)),
NegativeTimeout: time.Duration(*negative_ttl * float64(time.Second)), NegativeTimeout: time.Duration(*negative_ttl * float64(time.Second)),
PortableInodes: *portable, PortableInodes: *portable,
Debug: *debug,
} }
mountState, _, err := nodefs.MountRoot(flag.Arg(0), nodeFs.Root(), &mOpts) mountState, _, err := nodefs.MountRoot(flag.Arg(0), nodeFs.Root(), &mOpts)
if err != nil { if err != nil {
log.Fatal("Mount fail:", err) log.Fatal("Mount fail:", err)
} }
mountState.SetDebug(*debug)
mountState.Serve() mountState.Serve()
} }
...@@ -53,6 +53,7 @@ func main() { ...@@ -53,6 +53,7 @@ func main() {
opts := &nodefs.Options{ opts := &nodefs.Options{
AttrTimeout: time.Duration(*ttl * float64(time.Second)), AttrTimeout: time.Duration(*ttl * float64(time.Second)),
EntryTimeout: time.Duration(*ttl * float64(time.Second)), EntryTimeout: time.Duration(*ttl * float64(time.Second)),
Debug: *debug,
} }
state, _, err := nodefs.MountRoot(flag.Arg(0), root, opts) state, _, err := nodefs.MountRoot(flag.Arg(0), root, opts)
if err != nil { if err != nil {
...@@ -60,7 +61,6 @@ func main() { ...@@ -60,7 +61,6 @@ func main() {
os.Exit(1) os.Exit(1)
} }
state.SetDebug(*debug)
runtime.GC() runtime.GC()
if profFile != nil { if profFile != nil {
pprof.StartCPUProfile(profFile) pprof.StartCPUProfile(profFile)
......
...@@ -65,6 +65,9 @@ type MountOptions struct { ...@@ -65,6 +65,9 @@ type MountOptions struct {
// If set, return ENOSYS for Getxattr calls, so the kernel does not issue any // If set, return ENOSYS for Getxattr calls, so the kernel does not issue any
// Xattr operations at all. // Xattr operations at all.
DisableXAttrs bool DisableXAttrs bool
// If set, print debugging information.
Debug bool
} }
// RawFileSystem is an interface close to the FUSE wire protocol. // RawFileSystem is an interface close to the FUSE wire protocol.
......
...@@ -172,10 +172,13 @@ type Options struct { ...@@ -172,10 +172,13 @@ type Options struct {
NegativeTimeout time.Duration NegativeTimeout time.Duration
// If set, replace all uids with given UID. // If set, replace all uids with given UID.
// NewFileSystemOptions() will set this to the daemon's // NewOptions() will set this to the daemon's
// uid/gid. // uid/gid.
*fuse.Owner *fuse.Owner
// This option exists for compatibility and is ignored. // This option exists for compatibility and is ignored.
PortableInodes bool PortableInodes bool
// If set, print debug information.
Debug bool
} }
...@@ -36,6 +36,12 @@ func (n *nodeReadNode) Read(file File, dest []byte, off int64, context *fuse.Con ...@@ -36,6 +36,12 @@ func (n *nodeReadNode) Read(file File, dest []byte, off int64, context *fuse.Con
return fuse.ReadResultData(n.data[off:int(e)]), fuse.OK return fuse.ReadResultData(n.data[off:int(e)]), fuse.OK
} }
func (n *nodeReadNode) GetAttr(out *fuse.Attr, file File, context *fuse.Context) (code fuse.Status) {
out.Mode = fuse.S_IFREG | 0644
out.Size = uint64(len(n.data))
return fuse.OK
}
func (n *nodeReadNode) Lookup(out *fuse.Attr, name string, context *fuse.Context) (*Inode, fuse.Status) { func (n *nodeReadNode) Lookup(out *fuse.Attr, name string, context *fuse.Context) (*Inode, fuse.Status) {
out.Mode = fuse.S_IFREG | 0644 out.Mode = fuse.S_IFREG | 0644
out.Size = uint64(len(name)) out.Size = uint64(len(name))
...@@ -52,11 +58,10 @@ func TestNoOpen(t *testing.T) { ...@@ -52,11 +58,10 @@ func TestNoOpen(t *testing.T) {
root := newNodeReadNode(true, nil) root := newNodeReadNode(true, nil)
root.noOpen = true root.noOpen = true
s, _, err := MountRoot(dir, root, nil) s, _, err := MountRoot(dir, root, &Options{Debug: VerboseTest()})
if err != nil { if err != nil {
t.Fatalf("MountRoot: %v", err) t.Fatalf("MountRoot: %v", err)
} }
s.SetDebug(VerboseTest())
defer s.Unmount() defer s.Unmount()
go s.Serve() go s.Serve()
...@@ -92,7 +97,9 @@ func TestNodeRead(t *testing.T) { ...@@ -92,7 +97,9 @@ func TestNodeRead(t *testing.T) {
} }
root := newNodeReadNode(false, nil) root := newNodeReadNode(false, nil)
s, _, err := MountRoot(dir, root, nil) opts := NewOptions()
opts.Debug = true
s, _, err := MountRoot(dir, root, opts)
if err != nil { if err != nil {
t.Fatalf("MountRoot: %v", err) t.Fatalf("MountRoot: %v", err)
} }
...@@ -106,5 +113,4 @@ func TestNodeRead(t *testing.T) { ...@@ -106,5 +113,4 @@ func TestNodeRead(t *testing.T) {
if string(content) != want { if string(content) != want {
t.Fatalf("got %q, want %q", content, want) t.Fatalf("got %q, want %q", content, want)
} }
} }
...@@ -60,6 +60,7 @@ func NewFileSystemConnector(root Node, opts *Options) (c *FileSystemConnector) { ...@@ -60,6 +60,7 @@ func NewFileSystemConnector(root Node, opts *Options) (c *FileSystemConnector) {
// FUSE does not issue a LOOKUP for 1 (obviously), but it does // FUSE does not issue a LOOKUP for 1 (obviously), but it does
// issue a forget. This lookupUpdate is to make the counts match. // issue a forget. This lookupUpdate is to make the counts match.
c.lookupUpdate(c.rootNode) c.lookupUpdate(c.rootNode)
c.debug = opts.Debug
return c return c
} }
...@@ -69,7 +70,8 @@ func (c *FileSystemConnector) Server() *fuse.Server { ...@@ -69,7 +70,8 @@ func (c *FileSystemConnector) Server() *fuse.Server {
return c.server return c.server
} }
// SetDebug toggles printing of debug information. // SetDebug toggles printing of debug information. This function is
// deprecated. Set the Debug option in the Options struct instead.
func (c *FileSystemConnector) SetDebug(debug bool) { func (c *FileSystemConnector) SetDebug(debug bool) {
c.debug = debug c.debug = debug
} }
......
...@@ -7,7 +7,12 @@ import ( ...@@ -7,7 +7,12 @@ import (
// Mounts a filesystem with the given root node on the given directory // Mounts a filesystem with the given root node on the given directory
func MountRoot(mountpoint string, root Node, opts *Options) (*fuse.Server, *FileSystemConnector, error) { func MountRoot(mountpoint string, root Node, opts *Options) (*fuse.Server, *FileSystemConnector, error) {
conn := NewFileSystemConnector(root, opts) conn := NewFileSystemConnector(root, opts)
s, err := fuse.NewServer(conn.RawFS(), mountpoint, nil)
mountOpts := fuse.MountOptions{}
if opts != nil && opts.Debug {
mountOpts.Debug = opts.Debug
}
s, err := fuse.NewServer(conn.RawFS(), mountpoint, &mountOpts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
......
...@@ -27,16 +27,13 @@ func setupMemNodeTest(t *testing.T) (wd string, root Node, clean func()) { ...@@ -27,16 +27,13 @@ func setupMemNodeTest(t *testing.T) (wd string, root Node, clean func()) {
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
Debug: VerboseTest(),
}) })
connector.SetDebug(VerboseTest()) state, err := fuse.NewServer(connector.RawFS(), mnt, &fuse.MountOptions{Debug: VerboseTest()})
state, err := fuse.NewServer(connector.RawFS(), mnt, nil)
if err != nil { if err != nil {
t.Fatal("NewServer", err) t.Fatal("NewServer", err)
} }
//me.state.SetDebug(false)
state.SetDebug(VerboseTest())
// Unthreaded, but in background. // Unthreaded, but in background.
go state.Serve() go state.Serve()
return mnt, root, func() { return mnt, root, func() {
......
...@@ -262,7 +262,7 @@ func doBatchForget(server *Server, req *request) { ...@@ -262,7 +262,7 @@ func doBatchForget(server *Server, req *request) {
forgets := *(*[]_ForgetOne)(unsafe.Pointer(h)) forgets := *(*[]_ForgetOne)(unsafe.Pointer(h))
for i, f := range forgets { for i, f := range forgets {
if server.debug { if server.opts.Debug {
log.Printf("doBatchForget: forgetting %d of %d: NodeId: %d, Nlookup: %d", i+1, len(forgets), f.NodeId, f.Nlookup) log.Printf("doBatchForget: forgetting %d of %d: NodeId: %d, Nlookup: %d", i+1, len(forgets), f.NodeId, f.Nlookup)
} }
server.fileSystem.Forget(f.NodeId, f.Nlookup) server.fileSystem.Forget(f.NodeId, f.Nlookup)
......
...@@ -75,4 +75,7 @@ type PathNodeFsOptions struct { ...@@ -75,4 +75,7 @@ type PathNodeFsOptions struct {
// If ClientInodes is set, use Inode returned from GetAttr to // If ClientInodes is set, use Inode returned from GetAttr to
// find hard-linked files. // find hard-linked files.
ClientInodes bool ClientInodes bool
// Debug controls printing of debug information.
Debug bool
} }
...@@ -107,11 +107,11 @@ func xattrTestCase(t *testing.T, nm string, m map[string][]byte) (mountPoint str ...@@ -107,11 +107,11 @@ func xattrTestCase(t *testing.T, nm string, m map[string][]byte) (mountPoint str
} }
nfs := NewPathNodeFs(xfs, nil) nfs := NewPathNodeFs(xfs, nil)
state, _, err := nodefs.MountRoot(mountPoint, nfs.Root(), nil) state, _, err := nodefs.MountRoot(mountPoint, nfs.Root(),
&nodefs.Options{Debug: VerboseTest()})
if err != nil { if err != nil {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return mountPoint, func() { return mountPoint, func() {
......
...@@ -31,9 +31,6 @@ type Server struct { ...@@ -31,9 +31,6 @@ type Server struct {
// I/O with kernel and daemon. // I/O with kernel and daemon.
mountFd int mountFd int
// Dump debug info onto stdout.
debug bool
latencies LatencyMap latencies LatencyMap
opts *MountOptions opts *MountOptions
...@@ -54,8 +51,10 @@ type Server struct { ...@@ -54,8 +51,10 @@ type Server struct {
loops sync.WaitGroup loops sync.WaitGroup
} }
// SetDebug is deprecated. Use MountOptions.Debug instead.
func (ms *Server) SetDebug(dbg bool) { func (ms *Server) SetDebug(dbg bool) {
ms.debug = dbg // This will typically trigger the race detector.
ms.opts.Debug = dbg
} }
// KernelSettings returns the Init message from the kernel, so // KernelSettings returns the Init message from the kernel, so
...@@ -345,7 +344,7 @@ func (ms *Server) handleRequest(req *request) { ...@@ -345,7 +344,7 @@ func (ms *Server) handleRequest(req *request) {
req.status = ENOSYS req.status = ENOSYS
} }
if req.status.Ok() && ms.debug { if req.status.Ok() && ms.opts.Debug {
log.Println(req.InputDebug()) log.Println(req.InputDebug())
} }
...@@ -385,7 +384,7 @@ func (ms *Server) write(req *request) Status { ...@@ -385,7 +384,7 @@ func (ms *Server) write(req *request) Status {
} }
header := req.serializeHeader(req.flatDataSize()) header := req.serializeHeader(req.flatDataSize())
if ms.debug { if ms.opts.Debug {
log.Println(req.OutputDebug()) log.Println(req.OutputDebug())
} }
...@@ -422,7 +421,7 @@ func (ms *Server) InodeNotify(node uint64, off int64, length int64) Status { ...@@ -422,7 +421,7 @@ func (ms *Server) InodeNotify(node uint64, off int64, length int64) Status {
result := ms.write(&req) result := ms.write(&req)
ms.writeMu.Unlock() ms.writeMu.Unlock()
if ms.debug { if ms.opts.Debug {
log.Println("Response: INODE_NOTIFY", result) log.Println("Response: INODE_NOTIFY", result)
} }
return result return result
...@@ -464,7 +463,7 @@ func (ms *Server) DeleteNotify(parent uint64, child uint64, name string) Status ...@@ -464,7 +463,7 @@ func (ms *Server) DeleteNotify(parent uint64, child uint64, name string) Status
result := ms.write(&req) result := ms.write(&req)
ms.writeMu.Unlock() ms.writeMu.Unlock()
if ms.debug { if ms.opts.Debug {
log.Printf("Response: DELETE_NOTIFY: %v", result) log.Printf("Response: DELETE_NOTIFY: %v", result)
} }
return result return result
...@@ -499,7 +498,7 @@ func (ms *Server) EntryNotify(parent uint64, name string) Status { ...@@ -499,7 +498,7 @@ func (ms *Server) EntryNotify(parent uint64, name string) Status {
result := ms.write(&req) result := ms.write(&req)
ms.writeMu.Unlock() ms.writeMu.Unlock()
if ms.debug { if ms.opts.Debug {
log.Printf("Response: ENTRY_NOTIFY: %v", result) log.Printf("Response: ENTRY_NOTIFY: %v", result)
} }
return result return result
......
...@@ -39,14 +39,14 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) { ...@@ -39,14 +39,14 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
fs := &cacheFs{ fs := &cacheFs{
pathfs.NewLoopbackFileSystem(dir + "/orig"), pathfs.NewLoopbackFileSystem(dir + "/orig"),
} }
pfs := pathfs.NewPathNodeFs(fs, nil) pfs := pathfs.NewPathNodeFs(fs, &pathfs.PathNodeFsOptions{Debug: VerboseTest()})
state, conn, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(), nil)
opts := nodefs.NewOptions()
opts.Debug = VerboseTest()
state, _, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(), opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.SetDebug(VerboseTest())
conn.SetDebug(VerboseTest())
pfs.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return dir, pfs, func() { return dir, pfs, func() {
...@@ -140,11 +140,12 @@ func TestNonseekable(t *testing.T) { ...@@ -140,11 +140,12 @@ func TestNonseekable(t *testing.T) {
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := nodefs.MountRoot(dir, nfs.Root(), nil) opts := nodefs.NewOptions()
opts.Debug = VerboseTest()
state, _, err := nodefs.MountRoot(dir, nfs.Root(), opts)
if err != nil { if err != nil {
t.Fatalf("failed: %v", err) t.Fatalf("failed: %v", err)
} }
state.SetDebug(VerboseTest())
defer state.Unmount() defer state.Unmount()
go state.Serve() go state.Serve()
...@@ -172,15 +173,12 @@ func TestGetAttrRace(t *testing.T) { ...@@ -172,15 +173,12 @@ func TestGetAttrRace(t *testing.T) {
os.Mkdir(dir+"/orig", 0755) os.Mkdir(dir+"/orig", 0755)
fs := pathfs.NewLoopbackFileSystem(dir + "/orig") fs := pathfs.NewLoopbackFileSystem(dir + "/orig")
pfs := pathfs.NewPathNodeFs(fs, nil) pfs := pathfs.NewPathNodeFs(fs, &pathfs.PathNodeFsOptions{Debug: VerboseTest()})
state, conn, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(), state, _, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(),
&nodefs.Options{}) &nodefs.Options{Debug: VerboseTest()})
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.SetDebug(VerboseTest())
conn.SetDebug(VerboseTest())
pfs.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
defer state.Unmount() defer state.Unmount()
......
...@@ -41,11 +41,13 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) { ...@@ -41,11 +41,13 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
pathfs := pathfs.NewPathNodeFs(fs, nil) pathfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := nodefs.MountRoot(dir, pathfs.Root(), nil) opts := nodefs.NewOptions()
opts.Debug = VerboseTest()
state, _, err := nodefs.MountRoot(dir, pathfs.Root(), opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return dir, func() { return dir, func() {
......
...@@ -43,11 +43,12 @@ func TestDeleteNotify(t *testing.T) { ...@@ -43,11 +43,12 @@ func TestDeleteNotify(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
state, err := fuse.NewServer(conn.RawFS(), mnt, nil) state, err := fuse.NewServer(conn.RawFS(), mnt, &fuse.MountOptions{
Debug: VerboseTest(),
})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
defer state.Unmount() defer state.Unmount()
......
...@@ -144,11 +144,13 @@ func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func( ...@@ -144,11 +144,13 @@ func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := nodefs.MountRoot(dir, nfs.Root(), nil) opts := nodefs.NewOptions()
opts.Debug = VerboseTest()
state, _, err := nodefs.MountRoot(dir, nfs.Root(), opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
......
...@@ -96,16 +96,17 @@ func NewTestCase(t *testing.T) *testCase { ...@@ -96,16 +96,17 @@ func NewTestCase(t *testing.T) *testCase {
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
Debug: VerboseTest(),
}) })
tc.connector.SetDebug(VerboseTest())
tc.state, err = fuse.NewServer( tc.state, err = fuse.NewServer(
fuse.NewRawFileSystem(tc.connector.RawFS()), tc.mnt, &fuse.MountOptions{SingleThreaded: true}) fuse.NewRawFileSystem(tc.connector.RawFS()), tc.mnt, &fuse.MountOptions{
SingleThreaded: true,
Debug: VerboseTest(),
})
if err != nil { if err != nil {
t.Fatal("NewServer:", err) t.Fatal("NewServer:", err)
} }
tc.state.SetDebug(VerboseTest())
// Unthreaded, but in background. // Unthreaded, but in background.
go tc.state.Serve() go tc.state.Serve()
......
...@@ -84,6 +84,7 @@ func NewNotifyTest(t *testing.T) *NotifyTest { ...@@ -84,6 +84,7 @@ func NewNotifyTest(t *testing.T) *NotifyTest {
EntryTimeout: entryTtl, EntryTimeout: entryTtl,
AttrTimeout: entryTtl, AttrTimeout: entryTtl,
NegativeTimeout: entryTtl, NegativeTimeout: entryTtl,
Debug: VerboseTest(),
} }
me.pathfs = pathfs.NewPathNodeFs(me.fs, nil) me.pathfs = pathfs.NewPathNodeFs(me.fs, nil)
...@@ -91,7 +92,6 @@ func NewNotifyTest(t *testing.T) *NotifyTest { ...@@ -91,7 +92,6 @@ func NewNotifyTest(t *testing.T) *NotifyTest {
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
me.state.SetDebug(VerboseTest())
go me.state.Serve() go me.state.Serve()
return me return me
......
...@@ -38,11 +38,12 @@ func TestDefaultXAttr(t *testing.T) { ...@@ -38,11 +38,12 @@ func TestDefaultXAttr(t *testing.T) {
Node: nodefs.NewDefaultNode(), Node: nodefs.NewDefaultNode(),
} }
s, _, err := nodefs.MountRoot(dir, root, nil) opts := nodefs.NewOptions()
opts.Debug = VerboseTest()
s, _, err := nodefs.MountRoot(dir, root, opts)
if err != nil { if err != nil {
t.Fatalf("MountRoot: %v", err) t.Fatalf("MountRoot: %v", err)
} }
s.SetDebug(VerboseTest())
go s.Serve() go s.Serve()
defer s.Unmount() defer s.Unmount()
......
...@@ -57,14 +57,13 @@ type AutoUnionFsOptions struct { ...@@ -57,14 +57,13 @@ type AutoUnionFsOptions struct {
} }
const ( const (
_READONLY = "READONLY" _READONLY = "READONLY"
_STATUS = "status" _STATUS = "status"
_CONFIG = "config" _CONFIG = "config"
_DEBUG = "debug" _DEBUG = "debug"
_DEBUG_SETTING = "debug_setting" _ROOT = "root"
_ROOT = "root" _VERSION = "gounionfs_version"
_VERSION = "gounionfs_version" _SCAN_CONFIG = ".scan_config"
_SCAN_CONFIG = ".scan_config"
) )
func NewAutoUnionFs(directory string, options AutoUnionFsOptions) pathfs.FileSystem { func NewAutoUnionFs(directory string, options AutoUnionFsOptions) pathfs.FileSystem {
...@@ -238,10 +237,6 @@ func (fs *autoUnionFs) Readlink(path string, context *fuse.Context) (out string, ...@@ -238,10 +237,6 @@ func (fs *autoUnionFs) Readlink(path string, context *fuse.Context) (out string,
return fs.root, fuse.OK return fs.root, fuse.OK
} }
if comps[0] == _STATUS && comps[1] == _DEBUG_SETTING && fs.hasDebug() {
return "1", fuse.OK
}
if comps[0] != _CONFIG { if comps[0] != _CONFIG {
return "", fuse.ENOENT return "", fuse.ENOENT
} }
...@@ -270,11 +265,6 @@ func (fs *autoUnionFs) Symlink(pointedTo string, linkName string, context *fuse. ...@@ -270,11 +265,6 @@ func (fs *autoUnionFs) Symlink(pointedTo string, linkName string, context *fuse.
return fuse.EPERM return fuse.EPERM
} }
if comps[0] == _STATUS && comps[1] == _DEBUG_SETTING {
fs.SetDebug(true)
return fuse.OK
}
if comps[0] == _CONFIG { if comps[0] == _CONFIG {
roots := fs.getRoots(pointedTo) roots := fs.getRoots(pointedTo)
if roots == nil { if roots == nil {
...@@ -287,31 +277,12 @@ func (fs *autoUnionFs) Symlink(pointedTo string, linkName string, context *fuse. ...@@ -287,31 +277,12 @@ func (fs *autoUnionFs) Symlink(pointedTo string, linkName string, context *fuse.
return fuse.EPERM return fuse.EPERM
} }
func (fs *autoUnionFs) SetDebug(b bool) {
// TODO(hanwen): this should use locking.
fs.debug = b
fs.nodeFs.SetDebug(b)
conn := fs.nodeFs.Connector()
conn.SetDebug(b)
conn.Server().SetDebug(b)
}
func (fs *autoUnionFs) hasDebug() bool {
return fs.debug
}
func (fs *autoUnionFs) Unlink(path string, context *fuse.Context) (code fuse.Status) { func (fs *autoUnionFs) Unlink(path string, context *fuse.Context) (code fuse.Status) {
comps := strings.Split(path, "/") comps := strings.Split(path, "/")
if len(comps) != 2 { if len(comps) != 2 {
return fuse.EPERM return fuse.EPERM
} }
if comps[0] == _STATUS && comps[1] == _DEBUG_SETTING {
fs.SetDebug(false)
return fuse.OK
}
if comps[0] == _CONFIG && comps[1] != _SCAN_CONFIG { if comps[0] == _CONFIG && comps[1] != _SCAN_CONFIG {
code = fs.rmFs(comps[1]) code = fs.rmFs(comps[1])
} else { } else {
...@@ -333,12 +304,6 @@ func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, ...@@ -333,12 +304,6 @@ func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr,
return a, fuse.OK return a, fuse.OK
} }
if path == filepath.Join(_STATUS, _DEBUG_SETTING) && fs.hasDebug() {
return &fuse.Attr{
Mode: fuse.S_IFLNK | 0644,
}, fuse.OK
}
if path == filepath.Join(_STATUS, _VERSION) { if path == filepath.Join(_STATUS, _VERSION) {
a := &fuse.Attr{ a := &fuse.Attr{
Mode: fuse.S_IFREG | 0644, Mode: fuse.S_IFREG | 0644,
...@@ -393,9 +358,6 @@ func (fs *autoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status) ...@@ -393,9 +358,6 @@ func (fs *autoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status)
{Name: _DEBUG, Mode: fuse.S_IFREG | 0644}, {Name: _DEBUG, Mode: fuse.S_IFREG | 0644},
{Name: _ROOT, Mode: syscall.S_IFLNK | 0644}, {Name: _ROOT, Mode: syscall.S_IFLNK | 0644},
} }
if fs.hasDebug() {
stream = append(stream, fuse.DirEntry{Name: _DEBUG_SETTING, Mode: fuse.S_IFLNK | 0644})
}
return stream, fuse.OK return stream, fuse.OK
} }
......
// +build !race
package unionfs
import (
"os"
"testing"
"time"
)
// Ideally, this should check inject a logger rather than a boolean,
// so we can check if the messages are as we expect. Right now, this
// test requires visual inspection. When run with -v, the UNLINK reply
// and SYMLINK request are not printed.
func TestToggleDebug(t *testing.T) {
wd, clean := setup(t)
defer clean()
os.Remove(wd + "/mnt/status/debug_setting")
time.Sleep(10 * time.Millisecond)
if err := os.Symlink("xyz", wd+"/mnt/status/debug_setting"); err != nil {
t.Fatalf("Symlink: %v", err)
}
// now we should be in debug mode.
link, err := os.Readlink(wd + "/mnt/status/debug_setting")
if err != nil {
t.Fatalf("Readlink: %v", err)
}
if link != "1" {
t.Errorf("got %q want %q for debug_setting readlink",
link, "1")
}
}
...@@ -24,6 +24,10 @@ var testAOpts = AutoUnionFsOptions{ ...@@ -24,6 +24,10 @@ var testAOpts = AutoUnionFsOptions{
Version: "version", Version: "version",
} }
func init() {
testAOpts.Options.Debug = VerboseTest()
}
func WriteFile(t *testing.T, name string, contents string) { func WriteFile(t *testing.T, name string, contents string) {
err := ioutil.WriteFile(name, []byte(contents), 0644) err := ioutil.WriteFile(name, []byte(contents), 0644)
if err != nil { if err != nil {
...@@ -57,7 +61,6 @@ func setup(t *testing.T) (workdir string, cleanup func()) { ...@@ -57,7 +61,6 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
fs.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return wd, func() { return wd, func() {
......
...@@ -90,17 +90,17 @@ func setupUfs(t *testing.T) (wd string, cleanup func()) { ...@@ -90,17 +90,17 @@ func setupUfs(t *testing.T) (wd string, cleanup func()) {
AttrTimeout: entryTtl / 2, AttrTimeout: entryTtl / 2,
NegativeTimeout: entryTtl / 2, NegativeTimeout: entryTtl / 2,
PortableInodes: true, PortableInodes: true,
Debug: VerboseTest(),
} }
pathfs := pathfs.NewPathNodeFs(ufs, pathfs := pathfs.NewPathNodeFs(ufs,
&pathfs.PathNodeFsOptions{ClientInodes: true}) &pathfs.PathNodeFsOptions{ClientInodes: true,
state, conn, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts) Debug: opts.Debug,
})
state, _, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
conn.SetDebug(VerboseTest())
state.SetDebug(VerboseTest())
pathfs.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return wd, func() { return wd, func() {
...@@ -1154,6 +1154,7 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1154,6 +1154,7 @@ func TestUnionFsDisappearing(t *testing.T) {
EntryTimeout: entryTtl, EntryTimeout: entryTtl,
AttrTimeout: entryTtl, AttrTimeout: entryTtl,
NegativeTimeout: entryTtl, NegativeTimeout: entryTtl,
Debug: VerboseTest(),
} }
nfs := pathfs.NewPathNodeFs(ufs, nil) nfs := pathfs.NewPathNodeFs(ufs, nil)
...@@ -1162,7 +1163,6 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1162,7 +1163,6 @@ func TestUnionFsDisappearing(t *testing.T) {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
defer state.Unmount() defer state.Unmount()
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
err = ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644) err = ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644)
......
...@@ -59,18 +59,17 @@ func TestXAttrCaching(t *testing.T) { ...@@ -59,18 +59,17 @@ func TestXAttrCaching(t *testing.T) {
EntryTimeout: entryTtl / 2, EntryTimeout: entryTtl / 2,
AttrTimeout: entryTtl / 2, AttrTimeout: entryTtl / 2,
NegativeTimeout: entryTtl / 2, NegativeTimeout: entryTtl / 2,
Debug: VerboseTest(),
} }
pathfs := pathfs.NewPathNodeFs(ufs, pathfs := pathfs.NewPathNodeFs(ufs,
&pathfs.PathNodeFsOptions{ClientInodes: true}) &pathfs.PathNodeFsOptions{ClientInodes: true,
Debug: VerboseTest()})
server, conn, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts) server, _, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
server.SetDebug(VerboseTest())
conn.SetDebug(VerboseTest())
pathfs.SetDebug(VerboseTest())
defer server.Unmount() defer server.Unmount()
go server.Serve() go server.Serve()
......
...@@ -41,9 +41,6 @@ func (fs *MemTreeFs) String() string { ...@@ -41,9 +41,6 @@ func (fs *MemTreeFs) String() string {
return fs.Name return fs.Name
} }
func (fs *MemTreeFs) SetDebug(bool) {
}
func (fs *MemTreeFs) Root() nodefs.Node { func (fs *MemTreeFs) Root() nodefs.Node {
return fs.root return fs.root
} }
......
...@@ -27,11 +27,11 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) { ...@@ -27,11 +27,11 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
Debug: VerboseTest(),
}) })
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return mountPoint, func() { return mountPoint, func() {
......
...@@ -27,9 +27,10 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) { ...@@ -27,9 +27,10 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
} }
mountPoint, _ = ioutil.TempDir("", "") mountPoint, _ = ioutil.TempDir("", "")
state, _, err := nodefs.MountRoot(mountPoint, root, &nodefs.Options{}) state, _, err := nodefs.MountRoot(mountPoint, root, &nodefs.Options{
Debug: VerboseTest(),
})
state.SetDebug(VerboseTest())
go state.Serve() go state.Serve()
return mountPoint, func() { return mountPoint, func() {
......
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