github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/backend/local/local_unix.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // +build !windows 15 16 package local 17 18 import ( 19 "syscall" 20 21 "github.com/pingcap/errors" 22 "github.com/pingcap/failpoint" 23 24 "github.com/pingcap/br/pkg/lightning/log" 25 ) 26 27 const ( 28 // maximum max open files value 29 maxRLimit = 1000000 30 ) 31 32 func GetSystemRLimit() (Rlim_t, error) { 33 var rLimit syscall.Rlimit 34 err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) 35 return rLimit.Cur, err 36 } 37 38 // VerifyRLimit checks whether the open-file limit is large enough. 39 // In Local-backend, we need to read and write a lot of L0 SST files, so we need 40 // to check system max open files limit. 41 func VerifyRLimit(estimateMaxFiles Rlim_t) error { 42 if estimateMaxFiles > maxRLimit { 43 estimateMaxFiles = maxRLimit 44 } 45 var rLimit syscall.Rlimit 46 err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) 47 failpoint.Inject("GetRlimitValue", func(v failpoint.Value) { 48 limit := Rlim_t(v.(int)) 49 rLimit.Cur = limit 50 rLimit.Max = limit 51 err = nil 52 }) 53 if err != nil { 54 return errors.Trace(err) 55 } 56 if rLimit.Cur >= estimateMaxFiles { 57 return nil 58 } 59 if rLimit.Max < estimateMaxFiles { 60 // If the process is not started by privileged user, this will fail. 61 rLimit.Max = estimateMaxFiles 62 } 63 prevLimit := rLimit.Cur 64 rLimit.Cur = estimateMaxFiles 65 failpoint.Inject("SetRlimitError", func(v failpoint.Value) { 66 if v.(bool) { 67 err = errors.New("Setrlimit Injected Error") 68 } 69 }) 70 if err == nil { 71 err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) 72 } 73 if err != nil { 74 return errors.Annotatef(err, "the maximum number of open file descriptors is too small, got %d, expect greater or equal to %d", prevLimit, estimateMaxFiles) 75 } 76 77 // fetch the rlimit again to make sure our setting has taken effect 78 err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) 79 if err != nil { 80 return errors.Trace(err) 81 } 82 if rLimit.Cur < estimateMaxFiles { 83 helper := "Please manually execute `ulimit -n %d` to increase the open files limit." 84 return errors.Errorf("cannot update the maximum number of open file descriptors, expected: %d, got: %d. %s", 85 estimateMaxFiles, rLimit.Cur, helper) 86 } 87 88 log.L().Info("Set the maximum number of open file descriptors(rlimit)", 89 zapRlim_t("old", prevLimit), zapRlim_t("new", estimateMaxFiles)) 90 return nil 91 }