Skip to content

Commit

Permalink
Back out "fuse: remove Server.ready channel"
Browse files Browse the repository at this point in the history
This backs out commit f829e36.

Reason: the Server.ready channel is necessary on OSX. Document why.

Change-Id: I9cde964882f66c98cb726a343fad93c3929750e4
  • Loading branch information
hanwen committed Oct 31, 2024
1 parent d9023ab commit f662427
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
15 changes: 9 additions & 6 deletions fuse/mount_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func unixgramSocketpair() (l, r *os.File, err error) {

// Create a FUSE FS on the specified mount point. The returned
// mount point is always absolute.
func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
local, remote, err := unixgramSocketpair()
if err != nil {
return
Expand Down Expand Up @@ -65,9 +65,14 @@ func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
if err != nil {
return -1, err
}
ready := make(chan error, 1)

go func() {
// wait inside a goroutine or otherwise it would block forever for unknown reasons
// On macos, mount_osxfuse is not just a suid
// wrapper. It interacts with the FS setup, and will
// not exit until the filesystem has successfully
// responded to INIT and STATFS. This means we can
// only wait on the mount_osxfuse process after the
// server has fully started
if err := cmd.Wait(); err != nil {
err = fmt.Errorf("mount_osxfusefs failed: %v. Stderr: %s, Stdout: %s",
err, errOut.String(), out.String())
Expand All @@ -81,9 +86,7 @@ func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
// acquired through normal operations (e.g. open).
// Buf for fd, we have to set CLOEXEC manually
syscall.CloseOnExec(fd)
if err == nil {
err = <-ready
}

return fd, err
}

Expand Down
3 changes: 2 additions & 1 deletion fuse/mount_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func callMountFuseFs(mountPoint string, opts *MountOptions) (fd int, err error)
return int(f.Fd()), nil
}

func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
// Using the same logic from libfuse to prevent chaos
for {
f, err := os.OpenFile("/dev/null", os.O_RDWR, 0o000)
Expand Down Expand Up @@ -74,6 +74,7 @@ func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
// Buf for fd, we have to set CLOEXEC manually
syscall.CloseOnExec(fd)

close(ready)
return fd, err
}

Expand Down
9 changes: 6 additions & 3 deletions fuse/mount_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func unixgramSocketpair() (l, r *os.File, err error) {

// Create a FUSE FS on the specified mount point without using
// fusermount.
func mountDirect(mountPoint string, opts *MountOptions) (fd int, err error) {
func mountDirect(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
fd, err = syscall.Open("/dev/fuse", os.O_RDWR, 0) // use syscall.Open since we want an int fd
if err != nil {
return
Expand Down Expand Up @@ -76,6 +76,8 @@ func mountDirect(mountPoint string, opts *MountOptions) (fd int, err error) {
return
}

// success
close(ready)
return
}

Expand Down Expand Up @@ -135,9 +137,9 @@ func callFusermount(mountPoint string, opts *MountOptions) (fd int, err error) {

// Create a FUSE FS on the specified mount point. The returned
// mount point is always absolute.
func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
if opts.DirectMount || opts.DirectMountStrict {
fd, err := mountDirect(mountPoint, opts)
fd, err := mountDirect(mountPoint, opts, ready)
if err == nil {
return fd, nil
} else if opts.Debug {
Expand Down Expand Up @@ -166,6 +168,7 @@ func mount(mountPoint string, opts *MountOptions) (fd int, err error) {
// acquired through normal operations (e.g. open).
// Buf for fd, we have to set CLOEXEC manually
syscall.CloseOnExec(fd)
close(ready)
return fd, err
}

Expand Down
10 changes: 9 additions & 1 deletion fuse/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type Server struct {
loops sync.WaitGroup
serving bool // for preventing duplicate Serve() calls

// Used to implement WaitMount on macos.
ready chan error

// for implementing single threaded processing.
requestProcessingMu sync.Mutex

Expand Down Expand Up @@ -209,6 +212,7 @@ func NewServer(fs RawFileSystem, mountPoint string, opts *MountOptions) (*Server
maxReaders: maxReaders,
retrieveTab: make(map[uint64]*retrieveCacheRequest),
singleReader: useSingleReader,
ready: make(chan error, 1),
}
ms.reqPool.New = func() interface{} {
return &requestAlloc{
Expand Down Expand Up @@ -238,7 +242,7 @@ func NewServer(fs RawFileSystem, mountPoint string, opts *MountOptions) (*Server
}
mountPoint = filepath.Clean(filepath.Join(cwd, mountPoint))
}
fd, err := mount(mountPoint, &o)
fd, err := mount(mountPoint, &o, ms.ready)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -995,6 +999,10 @@ func (in *InitIn) supportsRenameSwap() bool {
// avoid racing between accessing the (empty or not yet mounted)
// mountpoint, and the OS trying to setup the user-space mount.
func (ms *Server) WaitMount() error {
err := <-ms.ready
if err != nil {
return err
}
if parseFuseFd(ms.mountPoint) >= 0 {
// Magic `/dev/fd/N` mountpoint. We don't know the real mountpoint, so
// we cannot run the poll hack.
Expand Down

0 comments on commit f662427

Please sign in to comment.