raise default fd limit to 8192
fixes #6247 Really, we need a global _resource_ manager service that can sum requests from the datastore, libp2p, etc. for more file descriptors. However, we don't have that. License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
Steven Allen committed
Apr 25, 2019 at 18:28 UTC
8ec386117b7f8b39790708503855ee461b530ff2
1 file changed
+49
-22
cmd/ipfs/util/ulimit.go
+49
-22
@@ -1,7 +1,6 @@
1
package util
2
3
import (
4
- "errors"
4
"fmt"
5
"os"
6
"strconv"
@@ -21,26 +20,25 @@ var (
20
setLimit func(uint64, uint64) error
21
)
22
24
-// maxFds is the maximum number of file descriptors that go-ipfs
25
-// can use. The default value is 2048. This can be overwritten by the
26
-// IPFS_FD_MAX env variable
27
-var maxFds = uint64(2048)
23
+// minimum file descriptor limit before we complain
24
+const minFds = 2048
25
29
-// setMaxFds sets the maxFds value from IPFS_FD_MAX
30
-// env variable if it's present on the system
31
-func setMaxFds() {
26
+// default max file descriptor limit.
27
+const maxFds = 8192
28
+
29
+// userMaxFDs returns the value of IPFS_FD_MAX
30
+func userMaxFDs() uint64 {
31
// check if the IPFS_FD_MAX is set up and if it does
32
// not have a valid fds number notify the user
33
if val := os.Getenv("IPFS_FD_MAX"); val != "" {
35
-
34
fds, err := strconv.ParseUint(val, 10, 64)
35
if err != nil {
36
log.Errorf("bad value for IPFS_FD_MAX: %s", err)
39
- return
37
+ return 0
38
}
41
-
42
- maxFds = fds
39
+ return fds
40
}
41
+ return 0
42
}
43
44
// ManageFdLimit raise the current max file descriptor count
@@ -50,7 +48,12 @@ func ManageFdLimit() (changed bool, newLimit uint64, err error) {
48
return false, 0, nil
49
}
50
53
- setMaxFds()
51
+ targetLimit := uint64(maxFds)
52
+ userLimit := userMaxFDs()
53
+ if userLimit > 0 {
54
+ targetLimit = userLimit
55
+ }
56
+
57
soft, hard, err := getLimit()
58
if err != nil {
59
return false, 0, err
@@ -65,23 +68,47 @@ func ManageFdLimit() (changed bool, newLimit uint64, err error) {
68
// the hard limit acts as a ceiling for the soft limit
69
// an unprivileged process may only set it's soft limit to a
70
// alue in the range from 0 up to the hard limit
68
- if err = setLimit(maxFds, maxFds); err != nil {
69
- if err != syscall.EPERM {
70
- return false, 0, fmt.Errorf("error setting: ulimit: %s", err)
71
+ err = setLimit(targetLimit, targetLimit)
72
+ switch err {
73
+ case nil:
74
+ newLimit = targetLimit
75
+ case syscall.EPERM:
76
+ // lower limit if necessary.
77
+ if targetLimit > hard {
78
+ targetLimit = hard
79
}
80
81
// the process does not have permission so we should only
82
// set the soft value
75
- if maxFds > hard {
76
- return false, 0, errors.New(
77
- "cannot set rlimit, IPFS_FD_MAX is larger than the hard limit",
83
+ err = setLimit(targetLimit, hard)
84
+ if err != nil {
85
+ err = fmt.Errorf("error setting ulimit wihout hard limit: %s", err)
86
+ break
87
+ }
88
+ newLimit = targetLimit
89
+
90
+ // Warn on lowered limit.
91
+
92
+ if newLimit < userLimit {
93
+ err = fmt.Errorf(
94
+ "failed to raise ulimit to IPFS_FD_MAX (%d): set to %d",
95
+ userLimit,
96
+ newLimit,
97
)
98
+ break
99
}
100
81
- if err = setLimit(maxFds, hard); err != nil {
82
- return false, 0, fmt.Errorf("error setting ulimit wihout hard limit: %s", err)
101
+ if userLimit == 0 && newLimit < minFds {
102
+ err = fmt.Errorf(
103
+ "failed to raise ulimit to minimum %d: set to %d",
104
+ minFds,
105
+ newLimit,
106
+ )
107
+ break
108
}
109
+ default:
110
+ err = fmt.Errorf("error setting: ulimit: %s", err)
111
}
112
86
- return true, maxFds, nil
113
+ return newLimit > 0, newLimit, err
114
}