github.com/a4a881d4/docker@v1.9.0-rc2/pkg/ulimit/ulimit.go (about) 1 // Package ulimit provides structure and helper function to parse and represent 2 // resource limits (Rlimit and Ulimit, its human friendly version). 3 package ulimit 4 5 import ( 6 "fmt" 7 "strconv" 8 "strings" 9 ) 10 11 // Ulimit is a human friendly version of Rlimit. 12 type Ulimit struct { 13 Name string 14 Hard int64 15 Soft int64 16 } 17 18 // Rlimit specifies the resource limits, such as max open files. 19 type Rlimit struct { 20 Type int `json:"type,omitempty"` 21 Hard uint64 `json:"hard,omitempty"` 22 Soft uint64 `json:"soft,omitempty"` 23 } 24 25 const ( 26 // magic numbers for making the syscall 27 // some of these are defined in the syscall package, but not all. 28 // Also since Windows client doesn't get access to the syscall package, need to 29 // define these here 30 rlimitAs = 9 31 rlimitCore = 4 32 rlimitCPU = 0 33 rlimitData = 2 34 rlimitFsize = 1 35 rlimitLocks = 10 36 rlimitMemlock = 8 37 rlimitMsgqueue = 12 38 rlimitNice = 13 39 rlimitNofile = 7 40 rlimitNproc = 6 41 rlimitRss = 5 42 rlimitRtprio = 14 43 rlimitRttime = 15 44 rlimitSigpending = 11 45 rlimitStack = 3 46 ) 47 48 var ulimitNameMapping = map[string]int{ 49 //"as": rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container. 50 "core": rlimitCore, 51 "cpu": rlimitCPU, 52 "data": rlimitData, 53 "fsize": rlimitFsize, 54 "locks": rlimitLocks, 55 "memlock": rlimitMemlock, 56 "msgqueue": rlimitMsgqueue, 57 "nice": rlimitNice, 58 "nofile": rlimitNofile, 59 "nproc": rlimitNproc, 60 "rss": rlimitRss, 61 "rtprio": rlimitRtprio, 62 "rttime": rlimitRttime, 63 "sigpending": rlimitSigpending, 64 "stack": rlimitStack, 65 } 66 67 // Parse parses and returns a Ulimit from the specified string. 68 func Parse(val string) (*Ulimit, error) { 69 parts := strings.SplitN(val, "=", 2) 70 if len(parts) != 2 { 71 return nil, fmt.Errorf("invalid ulimit argument: %s", val) 72 } 73 74 if _, exists := ulimitNameMapping[parts[0]]; !exists { 75 return nil, fmt.Errorf("invalid ulimit type: %s", parts[0]) 76 } 77 78 limitVals := strings.SplitN(parts[1], ":", 2) 79 if len(limitVals) > 2 { 80 return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1]) 81 } 82 83 soft, err := strconv.ParseInt(limitVals[0], 10, 64) 84 if err != nil { 85 return nil, err 86 } 87 88 hard := soft // in case no hard was set 89 if len(limitVals) == 2 { 90 hard, err = strconv.ParseInt(limitVals[1], 10, 64) 91 } 92 if soft > hard { 93 return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, hard) 94 } 95 96 return &Ulimit{Name: parts[0], Soft: soft, Hard: hard}, nil 97 } 98 99 // GetRlimit returns the RLimit corresponding to Ulimit. 100 func (u *Ulimit) GetRlimit() (*Rlimit, error) { 101 t, exists := ulimitNameMapping[u.Name] 102 if !exists { 103 return nil, fmt.Errorf("invalid ulimit name %s", u.Name) 104 } 105 106 return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil 107 } 108 109 func (u *Ulimit) String() string { 110 return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard) 111 }