1
1
package util
2
2
3
3
import (
4
- "errors"
5
4
"fmt"
6
5
"os"
7
6
"strconv"
@@ -21,26 +20,25 @@ var (
21
20
setLimit func (uint64 , uint64 ) error
22
21
)
23
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
28
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 {
32
31
// check if the IPFS_FD_MAX is set up and if it does
33
32
// not have a valid fds number notify the user
34
33
if val := os .Getenv ("IPFS_FD_MAX" ); val != "" {
35
-
36
34
fds , err := strconv .ParseUint (val , 10 , 64 )
37
35
if err != nil {
38
36
log .Errorf ("bad value for IPFS_FD_MAX: %s" , err )
39
- return
37
+ return 0
40
38
}
41
-
42
- maxFds = fds
39
+ return fds
43
40
}
41
+ return 0
44
42
}
45
43
46
44
// ManageFdLimit raise the current max file descriptor count
@@ -50,7 +48,12 @@ func ManageFdLimit() (changed bool, newLimit uint64, err error) {
50
48
return false , 0 , nil
51
49
}
52
50
53
- setMaxFds ()
51
+ targetLimit := uint64 (maxFds )
52
+ userLimit := userMaxFDs ()
53
+ if userLimit > 0 {
54
+ targetLimit = userLimit
55
+ }
56
+
54
57
soft , hard , err := getLimit ()
55
58
if err != nil {
56
59
return false , 0 , err
@@ -65,23 +68,47 @@ func ManageFdLimit() (changed bool, newLimit uint64, err error) {
65
68
// the hard limit acts as a ceiling for the soft limit
66
69
// an unprivileged process may only set it's soft limit to a
67
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
71
79
}
72
80
73
81
// the process does not have permission so we should only
74
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 ,
78
97
)
98
+ break
79
99
}
80
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
83
108
}
109
+ default :
110
+ err = fmt .Errorf ("error setting: ulimit: %s" , err )
84
111
}
85
112
86
- return true , maxFds , nil
113
+ return newLimit > 0 , newLimit , err
87
114
}
0 commit comments