lib/fs: Fix and update error about inotify watch limit (fixes #4833) (#4835)

This commit is contained in:
Simon Frei 2018-03-23 12:56:38 +01:00 committed by Jakob Borg
parent e7dc2f9190
commit da3b38ccce
4 changed files with 39 additions and 26 deletions

View File

@ -7,14 +7,12 @@
package fs package fs
import ( import (
"errors"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort" "sort"
"strings" "strings"
"syscall"
"testing" "testing"
"time" "time"
) )
@ -483,23 +481,3 @@ func TestRooted(t *testing.T) {
} }
} }
} }
func TestWatchErrorLinuxInterpretation(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("testing of linux specific error codes")
}
var errTooManyFiles syscall.Errno = 24
var errNoSpace syscall.Errno = 28
if !reachedMaxUserWatches(errTooManyFiles) {
t.Errorf("Errno %v should be recognised to be about inotify limits.", errTooManyFiles)
}
if !reachedMaxUserWatches(errNoSpace) {
t.Errorf("Errno %v should be recognised to be about inotify limits.", errNoSpace)
}
err := errors.New("Another error")
if reachedMaxUserWatches(err) {
t.Errorf("This error does not concern inotify limits: %#v", err)
}
}

View File

@ -42,7 +42,7 @@ func (f *BasicFilesystem) Watch(name string, ignore Matcher, ctx context.Context
if err := notify.WatchWithFilter(filepath.Join(absName, "..."), backendChan, absShouldIgnore, eventMask); err != nil { if err := notify.WatchWithFilter(filepath.Join(absName, "..."), backendChan, absShouldIgnore, eventMask); err != nil {
notify.Stop(backendChan) notify.Stop(backendChan)
if reachedMaxUserWatches(err) { if reachedMaxUserWatches(err) {
err = errors.New("failed to install inotify handler. Please increase inotify limits, see https://github.com/syncthing/syncthing-inotify#troubleshooting-for-folders-with-many-files-on-linux for more information") err = errors.New("failed to setup inotify handler. Please increase inotify limits, see https://docs.syncthing.net/users/faq.html#inotify-limits")
} }
return nil, err return nil, err
} }

View File

@ -8,11 +8,16 @@
package fs package fs
import "syscall" import (
"os"
"syscall"
)
func reachedMaxUserWatches(err error) bool { func reachedMaxUserWatches(err error) bool {
if errno, ok := err.(syscall.Errno); ok { if pathErr, ok := err.(*os.PathError); ok {
if errno, ok := pathErr.Err.(syscall.Errno); ok {
return errno == 24 || errno == 28 return errno == 24 || errno == 28
} }
}
return false return false
} }

View File

@ -10,11 +10,13 @@ package fs
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"syscall"
"testing" "testing"
"time" "time"
@ -178,6 +180,34 @@ func TestWatchOverflow(t *testing.T) {
testScenario(t, name, testCase, expectedEvents, allowedEvents, "") testScenario(t, name, testCase, expectedEvents, allowedEvents, "")
} }
func TestWatchErrorLinuxInterpretation(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("testing of linux specific error codes")
}
var errTooManyFiles = &os.PathError{
Op: "error while traversing",
Path: "foo",
Err: syscall.Errno(24),
}
var errNoSpace = &os.PathError{
Op: "error while traversing",
Path: "bar",
Err: syscall.Errno(28),
}
if !reachedMaxUserWatches(errTooManyFiles) {
t.Error("Underlying error syscall.Errno(24) should be recognised to be about inotify limits.")
}
if !reachedMaxUserWatches(errNoSpace) {
t.Error("Underlying error syscall.Errno(28) should be recognised to be about inotify limits.")
}
err := errors.New("Another error")
if reachedMaxUserWatches(err) {
t.Errorf("This error does not concern inotify limits: %#v", err)
}
}
// path relative to folder root, also creates parent dirs if necessary // path relative to folder root, also creates parent dirs if necessary
func createTestFile(name string, file string) string { func createTestFile(name string, file string) string {
joined := filepath.Join(name, file) joined := filepath.Join(name, file)