-
Notifications
You must be signed in to change notification settings - Fork 334
/
main.go
139 lines (127 loc) · 3.73 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This is main program driver for the loopback filesystem from
// github.com/hanwen/go-fuse/fs/, a filesystem that shunts operations
// to an underlying file system.
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"path"
"runtime/pprof"
"syscall"
"time"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
)
func writeMemProfile(fn string, sigs <-chan os.Signal) {
i := 0
for range sigs {
fn := fmt.Sprintf("%s-%d.memprof", fn, i)
i++
log.Printf("Writing mem profile to %s\n", fn)
f, err := os.Create(fn)
if err != nil {
log.Printf("Create: %v", err)
continue
}
pprof.WriteHeapProfile(f)
if err := f.Close(); err != nil {
log.Printf("close %v", err)
}
}
}
func main() {
log.SetFlags(log.Lmicroseconds)
// Scans the arg list and sets up flags
debug := flag.Bool("debug", false, "print debugging messages.")
other := flag.Bool("allow-other", false, "mount with -o allowother.")
quiet := flag.Bool("q", false, "quiet")
ro := flag.Bool("ro", false, "mount read-only")
directmount := flag.Bool("directmount", false, "try to call the mount syscall instead of executing fusermount")
directmountstrict := flag.Bool("directmountstrict", false, "like directmount, but don't fall back to fusermount")
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to this file")
memprofile := flag.String("memprofile", "", "write memory profile to this file")
flag.Parse()
if flag.NArg() < 2 {
fmt.Printf("usage: %s MOUNTPOINT ORIGINAL\n", path.Base(os.Args[0]))
fmt.Printf("\noptions:\n")
flag.PrintDefaults()
os.Exit(2)
}
if *cpuprofile != "" {
if !*quiet {
fmt.Printf("Writing cpu profile to %s\n", *cpuprofile)
}
f, err := os.Create(*cpuprofile)
if err != nil {
fmt.Println(err)
os.Exit(3)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
if *memprofile != "" {
if !*quiet {
log.Printf("send SIGUSR1 to %d to dump memory profile", os.Getpid())
}
profSig := make(chan os.Signal, 1)
signal.Notify(profSig, syscall.SIGUSR1)
go writeMemProfile(*memprofile, profSig)
}
if *cpuprofile != "" || *memprofile != "" {
if !*quiet {
fmt.Printf("Note: You must unmount gracefully, otherwise the profile file(s) will stay empty!\n")
}
}
orig := flag.Arg(1)
loopbackRoot, err := fs.NewLoopbackRoot(orig)
if err != nil {
log.Fatalf("NewLoopbackRoot(%s): %v\n", orig, err)
}
sec := time.Second
opts := &fs.Options{
// The timeout options are to be compatible with libfuse defaults,
// making benchmarking easier.
AttrTimeout: &sec,
EntryTimeout: &sec,
NullPermissions: true, // Leave file permissions on "000" files as-is
MountOptions: fuse.MountOptions{
AllowOther: *other,
Debug: *debug,
DirectMount: *directmount,
DirectMountStrict: *directmountstrict,
FsName: orig, // First column in "df -T": original dir
Name: "loopback", // Second column in "df -T" will be shown as "fuse." + Name
},
}
if opts.AllowOther {
// Make the kernel check file permissions for us
opts.MountOptions.Options = append(opts.MountOptions.Options, "default_permissions")
}
if *ro {
opts.MountOptions.Options = append(opts.MountOptions.Options, "ro")
}
// Enable diagnostics logging
if !*quiet {
opts.Logger = log.New(os.Stderr, "", 0)
}
server, err := fs.Mount(flag.Arg(0), loopbackRoot, opts)
if err != nil {
log.Fatalf("Mount fail: %v\n", err)
}
if !*quiet {
fmt.Println("Mounted!")
}
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
server.Unmount()
}()
server.Wait()
}