github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/runsc/boot/gofer_conf.go (about) 1 // Copyright 2023 The gVisor Authors. 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package boot 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/metacubex/gvisor/pkg/sentry/fsimpl/erofs" 22 ) 23 24 // GoferMountConfUpperType describes how upper layer is configured for the gofer mount. 25 type GoferMountConfUpperType byte 26 27 const ( 28 // NoOverlay indicates that this gofer mount has no upper layer. In this case, 29 // this gofer mount must have a lower layer (i.e. lower != NoneLower). 30 NoOverlay GoferMountConfUpperType = iota 31 32 // MemoryOverlay indicates that this gofer mount should be overlaid with a 33 // tmpfs backed by application memory. 34 MemoryOverlay 35 36 // SelfOverlay indicates that this gofer mount should be overlaid with a 37 // tmpfs backed by a host file in the mount's source directory. 38 SelfOverlay 39 40 // AnonOverlay indicates that this gofer mount should be overlaid with a 41 // tmpfs backed by a host file in an anonymous directory. 42 AnonOverlay 43 44 // UpperMax indicates the number of the valid upper layer types. 45 UpperMax 46 ) 47 48 // String returns a human-readable string representing the upper layer type. 49 func (u GoferMountConfUpperType) String() string { 50 switch u { 51 case NoOverlay: 52 return "none" 53 case MemoryOverlay: 54 return "memory" 55 case SelfOverlay: 56 return "self" 57 case AnonOverlay: 58 return "anon" 59 } 60 panic(fmt.Sprintf("Invalid gofer mount config upper layer type: %d", u)) 61 } 62 63 // Set sets the value. Set(String()) should be idempotent. 64 func (u *GoferMountConfUpperType) Set(v string) error { 65 switch v { 66 case "none": 67 *u = NoOverlay 68 case "memory": 69 *u = MemoryOverlay 70 case "self": 71 *u = SelfOverlay 72 case "anon": 73 *u = AnonOverlay 74 default: 75 return fmt.Errorf("invalid gofer mount config upper layer type: %s", v) 76 } 77 return nil 78 } 79 80 // GoferMountConfLowerType describes how lower layer is configured for the gofer mount. 81 type GoferMountConfLowerType byte 82 83 const ( 84 // NoneLower indicates that this gofer mount has no lower layer. 85 NoneLower GoferMountConfLowerType = iota 86 87 // Lisafs indicates that this gofer mount has a LISAFS lower layer. 88 Lisafs 89 90 // Erofs indicates that this gofer mount has an EROFS lower layer. 91 Erofs 92 93 // LowerMax indicates the number of the valid lower layer types. 94 LowerMax 95 ) 96 97 // String returns a human-readable string representing the lower layer type. 98 func (l GoferMountConfLowerType) String() string { 99 switch l { 100 case NoneLower: 101 return "none" 102 case Lisafs: 103 return "lisafs" 104 case Erofs: 105 return erofs.Name 106 } 107 panic(fmt.Sprintf("Invalid gofer mount config lower layer type: %d", l)) 108 } 109 110 // Set sets the value. Set(String()) should be idempotent. 111 func (l *GoferMountConfLowerType) Set(v string) error { 112 switch v { 113 case "none": 114 *l = NoneLower 115 case "lisafs": 116 *l = Lisafs 117 case erofs.Name: 118 *l = Erofs 119 default: 120 return fmt.Errorf("invalid gofer mount config lower layer type: %s", v) 121 } 122 return nil 123 } 124 125 // GoferMountConf describes how a gofer mount is configured in the sandbox. 126 type GoferMountConf struct { 127 Upper GoferMountConfUpperType `json:"upper"` 128 Lower GoferMountConfLowerType `json:"lower"` 129 } 130 131 // String returns a human-readable string representing the gofer mount config. 132 func (g GoferMountConf) String() string { 133 return fmt.Sprintf("%s:%s", g.Lower, g.Upper) 134 } 135 136 // Set sets the value. Set(String()) should be idempotent. 137 func (g *GoferMountConf) Set(v string) error { 138 parts := strings.Split(v, ":") 139 if len(parts) != 2 { 140 return fmt.Errorf("invalid gofer mount config format: %q", v) 141 } 142 if err := g.Lower.Set(parts[0]); err != nil { 143 return err 144 } 145 if err := g.Upper.Set(parts[1]); err != nil { 146 return err 147 } 148 if !g.valid() { 149 return fmt.Errorf("invalid gofer mount config: %+v", g) 150 } 151 return nil 152 } 153 154 // IsFilestorePresent returns true if a filestore file was associated with this. 155 func (g GoferMountConf) IsFilestorePresent() bool { 156 return g.Upper == SelfOverlay || g.Upper == AnonOverlay 157 } 158 159 // IsSelfBacked returns true if this mount is backed by a filestore in itself. 160 func (g GoferMountConf) IsSelfBacked() bool { 161 return g.Upper == SelfOverlay 162 } 163 164 // ShouldUseOverlayfs returns true if an overlayfs should be applied. 165 func (g GoferMountConf) ShouldUseOverlayfs() bool { 166 return g.Lower != NoneLower && g.Upper != NoOverlay 167 } 168 169 // ShouldUseTmpfs returns true if a tmpfs should be applied. 170 func (g GoferMountConf) ShouldUseTmpfs() bool { 171 // g.valid() implies that g.Upper != NoOverlay. 172 return g.Lower == NoneLower 173 } 174 175 // ShouldUseLisafs returns true if a lisafs client/server should be set up. 176 func (g GoferMountConf) ShouldUseLisafs() bool { 177 return g.Lower == Lisafs 178 } 179 180 // ShouldUseErofs returns true if an EROFS should be applied. 181 func (g GoferMountConf) ShouldUseErofs() bool { 182 return g.Lower == Erofs 183 } 184 185 // valid returns true if this is a valid gofer mount config. 186 func (g GoferMountConf) valid() bool { 187 return g.Lower < LowerMax && g.Upper < UpperMax && (g.Lower != NoneLower || g.Upper != NoOverlay) 188 } 189 190 // GoferMountConfFlags can be used with GoferMountConf flags that appear 191 // multiple times. 192 type GoferMountConfFlags []GoferMountConf 193 194 // String implements flag.Value. 195 func (g *GoferMountConfFlags) String() string { 196 confs := make([]string, 0, len(*g)) 197 for _, confVal := range *g { 198 confs = append(confs, confVal.String()) 199 } 200 return strings.Join(confs, ",") 201 } 202 203 // Get implements flag.Value. 204 func (g *GoferMountConfFlags) Get() any { 205 return g 206 } 207 208 // GetArray returns an array of mappings. 209 func (g *GoferMountConfFlags) GetArray() []GoferMountConf { 210 return *g 211 } 212 213 // Set implements flag.Value and appends a gofer configuration from the command 214 // line to the configs array. Set(String()) should be idempotent. 215 func (g *GoferMountConfFlags) Set(s string) error { 216 confs := strings.Split(s, ",") 217 for _, conf := range confs { 218 var confVal GoferMountConf 219 if err := confVal.Set(conf); err != nil { 220 return fmt.Errorf("invalid GoferMountConf value (%s): %v", conf, err) 221 } 222 *g = append(*g, confVal) 223 } 224 return nil 225 }