Add more debugging logs to the mounting process so we get more visibility for customer issues (#130)
parent
4e67748df3
commit
c62d7682a6
44
mount.go
44
mount.go
|
@ -17,6 +17,7 @@ package fuse
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -53,11 +54,17 @@ func Mount(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin the mounting process, which will continue in the background.
|
// Begin the mounting process, which will continue in the background.
|
||||||
|
if config.DebugLogger != nil {
|
||||||
|
config.DebugLogger.Println("Beginning the mounting kickoff process")
|
||||||
|
}
|
||||||
ready := make(chan error, 1)
|
ready := make(chan error, 1)
|
||||||
dev, err := mount(dir, config, ready)
|
dev, err := mount(dir, config, ready)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("mount: %v", err)
|
return nil, fmt.Errorf("mount: %v", err)
|
||||||
}
|
}
|
||||||
|
if config.DebugLogger != nil {
|
||||||
|
config.DebugLogger.Println("Completed the mounting kickoff process")
|
||||||
|
}
|
||||||
|
|
||||||
// Choose a parent context for ops.
|
// Choose a parent context for ops.
|
||||||
cfgCopy := *config
|
cfgCopy := *config
|
||||||
|
@ -65,6 +72,9 @@ func Mount(
|
||||||
cfgCopy.OpContext = context.Background()
|
cfgCopy.OpContext = context.Background()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.DebugLogger != nil {
|
||||||
|
config.DebugLogger.Println("Creating a connection object")
|
||||||
|
}
|
||||||
// Create a Connection object wrapping the device.
|
// Create a Connection object wrapping the device.
|
||||||
connection, err := newConnection(
|
connection, err := newConnection(
|
||||||
cfgCopy,
|
cfgCopy,
|
||||||
|
@ -74,6 +84,9 @@ func Mount(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("newConnection: %v", err)
|
return nil, fmt.Errorf("newConnection: %v", err)
|
||||||
}
|
}
|
||||||
|
if config.DebugLogger != nil {
|
||||||
|
config.DebugLogger.Println("Successfully created the connection")
|
||||||
|
}
|
||||||
|
|
||||||
// Serve the connection in the background. When done, set the join status.
|
// Serve the connection in the background. When done, set the join status.
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -82,6 +95,10 @@ func Mount(
|
||||||
close(mfs.joinStatusAvailable)
|
close(mfs.joinStatusAvailable)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if config.DebugLogger != nil {
|
||||||
|
config.DebugLogger.Println("Waiting for mounting process to complete")
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for the mount process to complete.
|
// Wait for the mount process to complete.
|
||||||
if err := <-ready; err != nil {
|
if err := <-ready; err != nil {
|
||||||
return nil, fmt.Errorf("mount (background): %v", err)
|
return nil, fmt.Errorf("mount (background): %v", err)
|
||||||
|
@ -110,13 +127,19 @@ func checkMountPoint(dir string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fusermount(binary string, argv []string, additionalEnv []string, wait bool) (*os.File, error) {
|
func fusermount(binary string, argv []string, additionalEnv []string, wait bool, debugLogger *log.Logger) (*os.File, error) {
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Creating a socket pair")
|
||||||
|
}
|
||||||
// Create a socket pair.
|
// Create a socket pair.
|
||||||
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
|
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Socketpair: %v", err)
|
return nil, fmt.Errorf("Socketpair: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Creating files to wrap the sockets")
|
||||||
|
}
|
||||||
// Wrap the sockets into os.File objects that we will pass off to fusermount.
|
// Wrap the sockets into os.File objects that we will pass off to fusermount.
|
||||||
writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes")
|
writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes")
|
||||||
defer writeFile.Close()
|
defer writeFile.Close()
|
||||||
|
@ -124,6 +147,9 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool)
|
||||||
readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads")
|
readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads")
|
||||||
defer readFile.Close()
|
defer readFile.Close()
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Starting fusermount/os mount")
|
||||||
|
}
|
||||||
// Start fusermount/mount_macfuse/mount_osxfuse.
|
// Start fusermount/mount_macfuse/mount_osxfuse.
|
||||||
cmd := exec.Command(binary, argv...)
|
cmd := exec.Command(binary, argv...)
|
||||||
cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3")
|
cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3")
|
||||||
|
@ -141,6 +167,9 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool)
|
||||||
return nil, fmt.Errorf("running %v: %v", binary, err)
|
return nil, fmt.Errorf("running %v: %v", binary, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Wrapping socket pair in a connection")
|
||||||
|
}
|
||||||
// Wrap the socket file in a connection.
|
// Wrap the socket file in a connection.
|
||||||
c, err := net.FileConn(readFile)
|
c, err := net.FileConn(readFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -148,12 +177,18 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool)
|
||||||
}
|
}
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Checking that we have a unix domain socket")
|
||||||
|
}
|
||||||
// We expect to have a Unix domain socket.
|
// We expect to have a Unix domain socket.
|
||||||
uc, ok := c.(*net.UnixConn)
|
uc, ok := c.(*net.UnixConn)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("Expected UnixConn, got %T", c)
|
return nil, fmt.Errorf("Expected UnixConn, got %T", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Read a message from socket")
|
||||||
|
}
|
||||||
// Read a message.
|
// Read a message.
|
||||||
buf := make([]byte, 32) // expect 1 byte
|
buf := make([]byte, 32) // expect 1 byte
|
||||||
oob := make([]byte, 32) // expect 24 bytes
|
oob := make([]byte, 32) // expect 24 bytes
|
||||||
|
@ -175,6 +210,10 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool)
|
||||||
|
|
||||||
scm := scms[0]
|
scm := scms[0]
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Successfully read the socket message.")
|
||||||
|
}
|
||||||
|
|
||||||
// Pull out the FD returned by fusermount
|
// Pull out the FD returned by fusermount
|
||||||
gotFds, err := syscall.ParseUnixRights(&scm)
|
gotFds, err := syscall.ParseUnixRights(&scm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -185,6 +224,9 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool)
|
||||||
return nil, fmt.Errorf("wanted 1 fd; got %#v", gotFds)
|
return nil, fmt.Errorf("wanted 1 fd; got %#v", gotFds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debugLogger != nil {
|
||||||
|
debugLogger.Println("Converting FD into os.File")
|
||||||
|
}
|
||||||
// Turn the FD into an os.File.
|
// Turn the FD into an os.File.
|
||||||
return os.NewFile(uintptr(gotFds[0]), "/dev/fuse"), nil
|
return os.NewFile(uintptr(gotFds[0]), "/dev/fuse"), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,7 @@ func callMountCommFD(
|
||||||
env = append(env, "_FUSE_COMMVERS=2")
|
env = append(env, "_FUSE_COMMVERS=2")
|
||||||
argv = append(argv, dir)
|
argv = append(argv, dir)
|
||||||
|
|
||||||
return fusermount(bin, argv, env, false)
|
return fusermount(bin, argv, env, false, cfg.DebugLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin the process of mounting at the given directory, returning a connection
|
// Begin the process of mounting at the given directory, returning a connection
|
||||||
|
|
|
@ -55,6 +55,9 @@ var mountflagopts = map[string]func(uintptr) uintptr{
|
||||||
var errFallback = errors.New("sentinel: fallback to fusermount(1)")
|
var errFallback = errors.New("sentinel: fallback to fusermount(1)")
|
||||||
|
|
||||||
func directmount(dir string, cfg *MountConfig) (*os.File, error) {
|
func directmount(dir string, cfg *MountConfig) (*os.File, error) {
|
||||||
|
if cfg.DebugLogger != nil {
|
||||||
|
cfg.DebugLogger.Println("Preparing for direct mounting")
|
||||||
|
}
|
||||||
// We use syscall.Open + os.NewFile instead of os.OpenFile so that the file
|
// We use syscall.Open + os.NewFile instead of os.OpenFile so that the file
|
||||||
// is opened in blocking mode. When opened in non-blocking mode, the Go
|
// is opened in blocking mode. When opened in non-blocking mode, the Go
|
||||||
// runtime tries to use poll(2), which does not work with /dev/fuse.
|
// runtime tries to use poll(2), which does not work with /dev/fuse.
|
||||||
|
@ -63,6 +66,10 @@ func directmount(dir string, cfg *MountConfig) (*os.File, error) {
|
||||||
return nil, errFallback
|
return nil, errFallback
|
||||||
}
|
}
|
||||||
dev := os.NewFile(uintptr(fd), "/dev/fuse")
|
dev := os.NewFile(uintptr(fd), "/dev/fuse")
|
||||||
|
|
||||||
|
if cfg.DebugLogger != nil {
|
||||||
|
cfg.DebugLogger.Println("Successfully opened the /dev/fuse in blocking mode")
|
||||||
|
}
|
||||||
// As per libfuse/fusermount.c:847: https://bit.ly/2SgtWYM#L847
|
// As per libfuse/fusermount.c:847: https://bit.ly/2SgtWYM#L847
|
||||||
data := fmt.Sprintf("fd=%d,rootmode=40000,user_id=%d,group_id=%d",
|
data := fmt.Sprintf("fd=%d,rootmode=40000,user_id=%d,group_id=%d",
|
||||||
dev.Fd(), os.Getuid(), os.Getgid())
|
dev.Fd(), os.Getuid(), os.Getgid())
|
||||||
|
@ -84,6 +91,10 @@ func directmount(dir string, cfg *MountConfig) (*os.File, error) {
|
||||||
}
|
}
|
||||||
delete(opts, "subtype")
|
delete(opts, "subtype")
|
||||||
data += "," + mapToOptionsString(opts)
|
data += "," + mapToOptionsString(opts)
|
||||||
|
|
||||||
|
if cfg.DebugLogger != nil {
|
||||||
|
cfg.DebugLogger.Println("Starting the unix mounting")
|
||||||
|
}
|
||||||
if err := unix.Mount(
|
if err := unix.Mount(
|
||||||
cfg.FSName, // source
|
cfg.FSName, // source
|
||||||
dir, // target
|
dir, // target
|
||||||
|
@ -97,6 +108,9 @@ func directmount(dir string, cfg *MountConfig) (*os.File, error) {
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if cfg.DebugLogger != nil {
|
||||||
|
cfg.DebugLogger.Println("Unix mounting completed successfully")
|
||||||
|
}
|
||||||
return dev, nil
|
return dev, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +122,9 @@ func mount(dir string, cfg *MountConfig, ready chan<- error) (*os.File, error) {
|
||||||
// On linux, mounting is never delayed.
|
// On linux, mounting is never delayed.
|
||||||
ready <- nil
|
ready <- nil
|
||||||
|
|
||||||
|
if cfg.DebugLogger != nil {
|
||||||
|
cfg.DebugLogger.Println("Parsing fuse file descriptor")
|
||||||
|
}
|
||||||
// If the mountpoint is /dev/fd/N, assume that the file descriptor N is an
|
// If the mountpoint is /dev/fd/N, assume that the file descriptor N is an
|
||||||
// already open FUSE channel. Parse it, cast it to an fd, and don't do any
|
// already open FUSE channel. Parse it, cast it to an fd, and don't do any
|
||||||
// other part of the mount dance.
|
// other part of the mount dance.
|
||||||
|
@ -120,6 +137,9 @@ func mount(dir string, cfg *MountConfig, ready chan<- error) (*os.File, error) {
|
||||||
// have the CAP_SYS_ADMIN capability.
|
// have the CAP_SYS_ADMIN capability.
|
||||||
dev, err := directmount(dir, cfg)
|
dev, err := directmount(dir, cfg)
|
||||||
if err == errFallback {
|
if err == errFallback {
|
||||||
|
if cfg.DebugLogger != nil {
|
||||||
|
cfg.DebugLogger.Println("Directmount failed. Trying fallback.")
|
||||||
|
}
|
||||||
fusermountPath, err := findFusermount()
|
fusermountPath, err := findFusermount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -129,7 +149,7 @@ func mount(dir string, cfg *MountConfig, ready chan<- error) (*os.File, error) {
|
||||||
"--",
|
"--",
|
||||||
dir,
|
dir,
|
||||||
}
|
}
|
||||||
return fusermount(fusermountPath, argv, []string{}, true)
|
return fusermount(fusermountPath, argv, []string{}, true, cfg.DebugLogger)
|
||||||
}
|
}
|
||||||
return dev, err
|
return dev, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue