Skip to content

Commit 3ec902d

Browse files
committed
Merge pull request #9486 from btw616:erofs-CR-and-rootfs-support
PiperOrigin-RevId: 581036949
2 parents 917bee5 + bff1150 commit 3ec902d

File tree

19 files changed

+1069
-354
lines changed

19 files changed

+1069
-354
lines changed

images/default/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ RUN apt-get update && apt-get install -y curl gnupg2 git \
88
apt-transport-https ca-certificates gnupg-agent \
99
software-properties-common \
1010
pkg-config libffi-dev patch diffutils libssl-dev iptables kmod \
11-
clang crossbuild-essential-amd64 erofs-utils
11+
clang crossbuild-essential-amd64 erofs-utils busybox-static
1212

1313
# Install Docker client for the website build.
1414
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -

pkg/sentry/fsimpl/erofs/save_restore.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ func (fs *filesystem) CompleteRestore(ctx context.Context, opts vfs.CompleteRest
5050
if got, want := newImage.SuperBlock(), fs.image.SuperBlock(); got != want {
5151
return fmt.Errorf("superblock mismatch detected on restore, got %+v, expected %+v", got, want)
5252
}
53-
fs.image = newImage
53+
// We need to update the image in place, as there are other pointers
54+
// pointing to this image as well.
55+
*fs.image = *newImage
5456
return nil
5557
}
5658

runsc/boot/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ go_test(
148148
"//pkg/cpuid",
149149
"//pkg/fspath",
150150
"//pkg/log",
151+
"//pkg/sentry/fsimpl/erofs",
151152
"//pkg/sentry/kernel/auth",
152153
"//pkg/sentry/seccheck",
153154
"//pkg/sentry/vfs",

runsc/boot/gofer_conf.go

Lines changed: 148 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,52 +16,175 @@ package boot
1616

1717
import (
1818
"fmt"
19-
"strconv"
2019
"strings"
20+
21+
"gvisor.dev/gvisor/pkg/sentry/fsimpl/erofs"
2122
)
2223

23-
// GoferMountConf describes how a gofer mount is configured in the sandbox.
24-
type GoferMountConf int
24+
// GoferMountConfUpperType describes how upper layer is configured for the gofer mount.
25+
type GoferMountConfUpperType byte
2526

2627
const (
27-
// VanillaGofer indicates that this gofer mount has no special configuration.
28-
VanillaGofer GoferMountConf = iota
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
2931

30-
// MemoryOverlay indicates that this gofer mount should be overlaid with an
31-
// overlayfs backed by application memory.
32+
// MemoryOverlay indicates that this gofer mount should be overlaid with a
33+
// tmpfs backed by application memory.
3234
MemoryOverlay
3335

34-
// SelfOverlay indicates that this gofer mount should be overlaid with an
35-
// overlayfs backed by a host file in the mount's source directory.
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.
3638
SelfOverlay
3739

38-
// AnonOverlay indicates that this gofer mount should be overlaid with an
39-
// overlayfs backed by a host file in an anonymous directory.
40+
// AnonOverlay indicates that this gofer mount should be overlaid with a
41+
// tmpfs backed by a host file in an anonymous directory.
4042
AnonOverlay
4143

42-
// SelfTmpfs indicates that this gofer mount should be overlaid with a tmpfs
43-
// mount backed by a host file in the mount's source directory.
44-
SelfTmpfs
44+
// UpperMax indicates the number of the valid upper layer types.
45+
UpperMax
4546
)
4647

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+
47154
// IsFilestorePresent returns true if a filestore file was associated with this.
48155
func (g GoferMountConf) IsFilestorePresent() bool {
49-
return g == SelfOverlay || g == AnonOverlay || g == SelfTmpfs
156+
return g.Upper == SelfOverlay || g.Upper == AnonOverlay
50157
}
51158

52159
// IsSelfBacked returns true if this mount is backed by a filestore in itself.
53160
func (g GoferMountConf) IsSelfBacked() bool {
54-
return g == SelfOverlay || g == SelfTmpfs
161+
return g.Upper == SelfOverlay
55162
}
56163

57164
// ShouldUseOverlayfs returns true if an overlayfs should be applied.
58165
func (g GoferMountConf) ShouldUseOverlayfs() bool {
59-
return g == MemoryOverlay || g == SelfOverlay || g == AnonOverlay
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
60173
}
61174

62175
// ShouldUseLisafs returns true if a lisafs client/server should be set up.
63176
func (g GoferMountConf) ShouldUseLisafs() bool {
64-
return g == VanillaGofer || g.ShouldUseOverlayfs()
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)
65188
}
66189

67190
// GoferMountConfFlags can be used with GoferMountConf flags that appear
@@ -70,11 +193,11 @@ type GoferMountConfFlags []GoferMountConf
70193

71194
// String implements flag.Value.
72195
func (g *GoferMountConfFlags) String() string {
73-
confVals := make([]string, 0, len(*g))
196+
confs := make([]string, 0, len(*g))
74197
for _, confVal := range *g {
75-
confVals = append(confVals, strconv.Itoa(int(confVal)))
198+
confs = append(confs, confVal.String())
76199
}
77-
return strings.Join(confVals, ",")
200+
return strings.Join(confs, ",")
78201
}
79202

80203
// Get implements flag.Value.
@@ -92,14 +215,11 @@ func (g *GoferMountConfFlags) GetArray() []GoferMountConf {
92215
func (g *GoferMountConfFlags) Set(s string) error {
93216
confs := strings.Split(s, ",")
94217
for _, conf := range confs {
95-
confVal, err := strconv.Atoi(conf)
96-
if err != nil {
97-
return fmt.Errorf("invalid GoferMountConf value (%d): %v", confVal, err)
98-
}
99-
if confVal > int(SelfTmpfs) {
100-
return fmt.Errorf("invalid GoferMountConf value (%d)", confVal)
218+
var confVal GoferMountConf
219+
if err := confVal.Set(conf); err != nil {
220+
return fmt.Errorf("invalid GoferMountConf value (%s): %v", conf, err)
101221
}
102-
*g = append(*g, GoferMountConf(confVal))
222+
*g = append(*g, confVal)
103223
}
104224
return nil
105225
}

0 commit comments

Comments
 (0)