File: mount_linux_test.go

package info (click to toggle)
golang-github-hanwen-go-fuse 2.1.0%2Bgit20220822.58a7e14-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,292 kB
  • sloc: cpp: 78; sh: 43; makefile: 16
file content (100 lines) | stat: -rw-r--r-- 2,640 bytes parent folder | download
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
package fuse

import (
	"fmt"
	"io/ioutil"
	"syscall"
	"testing"
)

// TestMountDevFd tests the special `/dev/fd/N` mountpoint syntax, where a
// privileged parent process opens /dev/fuse and calls mount() for us.
//
// In this test, we simulate a privileged parent by using the `fusermount` suid
// helper.
func TestMountDevFd(t *testing.T) {
	realMountPoint, err := ioutil.TempDir("", t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer syscall.Rmdir(realMountPoint)

	// Call the fusermount suid helper to obtain the file descriptor in place
	// of a privileged parent.
	var fuOpts MountOptions
	fd, err := callFusermount(realMountPoint, &fuOpts)
	if err != nil {
		t.Fatal(err)
	}
	fdMountPoint := fmt.Sprintf("/dev/fd/%d", fd)

	// Real test starts here:
	// See if we can feed fdMountPoint to NewServer
	fs := NewDefaultRawFileSystem()
	opts := MountOptions{
		Debug: true,
	}
	srv, err := NewServer(fs, fdMountPoint, &opts)
	if err != nil {
		t.Fatal(err)
	}

	go srv.Serve()
	if err := srv.WaitMount(); err != nil {
		t.Fatal(err)
	}

	// If we are actually mounted, we should get ENOSYS.
	//
	// This won't deadlock despite pollHack not working for `/dev/fd/N` mounts
	// because functions in the syscall package don't use the poller.
	var st syscall.Stat_t
	err = syscall.Stat(realMountPoint, &st)
	if err != syscall.ENOSYS {
		t.Errorf("expected ENOSYS, got %v", err)
	}

	// Cleanup is somewhat tricky because `srv` does not know about
	// `realMountPoint`, so `srv.Unmount()` cannot work.
	//
	// A normal user has to call `fusermount -u` for themselves to unmount.
	// But in this test we can monkey-patch `srv.mountPoint`.
	srv.mountPoint = realMountPoint
	if err := srv.Unmount(); err != nil {
		t.Error(err)
	}
}

// TestMountMaxWrite makes sure that mounting works with all MaxWrite settings.
// We used to fail with EINVAL below 8k because readPool got too small.
func TestMountMaxWrite(t *testing.T) {
	opts := []MountOptions{
		{MaxWrite: 0}, // go-fuse default
		{MaxWrite: 1},
		{MaxWrite: 123},
		{MaxWrite: 1 * 1024},
		{MaxWrite: 4 * 1024},
		{MaxWrite: 8 * 1024},
		{MaxWrite: 64 * 1024},  // go-fuse default
		{MaxWrite: 128 * 1024}, // limit in Linux v4.19 and older
		{MaxWrite: 999 * 1024},
		{MaxWrite: 1024 * 1024}, // limit in Linux v4.20+
	}
	for _, o := range opts {
		name := fmt.Sprintf("MaxWrite%d", o.MaxWrite)
		t.Run(name, func(t *testing.T) {
			mnt, err := ioutil.TempDir("", name)
			if err != nil {
				t.Fatal(err)
			}
			fs := NewDefaultRawFileSystem()
			srv, err := NewServer(fs, mnt, &o)
			if err != nil {
				t.Error(err)
			} else {
				go srv.Serve()
				srv.Unmount()
			}
		})
	}
}