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 140 141
|
// 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.")
idmap := flag.Bool("idmapped", false, "enable id-mapped mount")
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,
IDMappedMount: *idmap,
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()
}
|