github.com/hanwen/go-fuse@v1.0.0/example/loopback/main.go (about) 1 // Copyright 2016 the Go-FUSE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Mounts another directory as loopback for testing and benchmarking 6 // purposes. 7 8 package main 9 10 import ( 11 "flag" 12 "fmt" 13 "log" 14 "os" 15 "os/signal" 16 "path" 17 "path/filepath" 18 "runtime/pprof" 19 "syscall" 20 "time" 21 22 "github.com/hanwen/go-fuse/fuse" 23 "github.com/hanwen/go-fuse/fuse/nodefs" 24 "github.com/hanwen/go-fuse/fuse/pathfs" 25 ) 26 27 func writeMemProfile(fn string, sigs <-chan os.Signal) { 28 i := 0 29 for range sigs { 30 fn := fmt.Sprintf("%s-%d.memprof", fn, i) 31 i++ 32 33 log.Printf("Writing mem profile to %s\n", fn) 34 f, err := os.Create(fn) 35 if err != nil { 36 log.Printf("Create: %v", err) 37 continue 38 } 39 pprof.WriteHeapProfile(f) 40 if err := f.Close(); err != nil { 41 log.Printf("close %v", err) 42 } 43 } 44 } 45 46 func main() { 47 log.SetFlags(log.Lmicroseconds) 48 // Scans the arg list and sets up flags 49 debug := flag.Bool("debug", false, "print debugging messages.") 50 other := flag.Bool("allow-other", false, "mount with -o allowother.") 51 enableLinks := flag.Bool("l", false, "Enable hard link support") 52 cpuprofile := flag.String("cpuprofile", "", "write cpu profile to this file") 53 memprofile := flag.String("memprofile", "", "write memory profile to this file") 54 flag.Parse() 55 if flag.NArg() < 2 { 56 fmt.Printf("usage: %s MOUNTPOINT ORIGINAL\n", path.Base(os.Args[0])) 57 fmt.Printf("\noptions:\n") 58 flag.PrintDefaults() 59 os.Exit(2) 60 } 61 if *cpuprofile != "" { 62 fmt.Printf("Writing cpu profile to %s\n", *cpuprofile) 63 f, err := os.Create(*cpuprofile) 64 if err != nil { 65 fmt.Println(err) 66 os.Exit(3) 67 } 68 pprof.StartCPUProfile(f) 69 defer pprof.StopCPUProfile() 70 } 71 if *memprofile != "" { 72 log.Printf("send SIGUSR1 to %d to dump memory profile", os.Getpid()) 73 profSig := make(chan os.Signal, 1) 74 signal.Notify(profSig, syscall.SIGUSR1) 75 go writeMemProfile(*memprofile, profSig) 76 } 77 if *cpuprofile != "" || *memprofile != "" { 78 fmt.Printf("Note: You must unmount gracefully, otherwise the profile file(s) will stay empty!\n") 79 } 80 81 var finalFs pathfs.FileSystem 82 orig := flag.Arg(1) 83 loopbackfs := pathfs.NewLoopbackFileSystem(orig) 84 finalFs = loopbackfs 85 86 opts := &nodefs.Options{ 87 // These options are to be compatible with libfuse defaults, 88 // making benchmarking easier. 89 NegativeTimeout: time.Second, 90 AttrTimeout: time.Second, 91 EntryTimeout: time.Second, 92 } 93 // Enable ClientInodes so hard links work 94 pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: *enableLinks} 95 pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts) 96 conn := nodefs.NewFileSystemConnector(pathFs.Root(), opts) 97 mountPoint := flag.Arg(0) 98 origAbs, _ := filepath.Abs(orig) 99 mOpts := &fuse.MountOptions{ 100 AllowOther: *other, 101 Name: "loopbackfs", 102 FsName: origAbs, 103 Debug: *debug, 104 } 105 state, err := fuse.NewServer(conn.RawFS(), mountPoint, mOpts) 106 if err != nil { 107 fmt.Printf("Mount fail: %v\n", err) 108 os.Exit(1) 109 } 110 111 fmt.Println("Mounted!") 112 state.Serve() 113 }