Added integration tests for mounting tmpfs with size option enabled.
PiperOrigin-RevId: 444705540
This commit is contained in:
parent
bf251f1838
commit
ce91143bdc
|
@ -202,7 +202,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
|||
var maxSizeInPages uint64
|
||||
if ok {
|
||||
delete(mopts, "size")
|
||||
maxSizeInBytes, err := strconv.ParseUint(maxSizeStr, 10, 64)
|
||||
maxSizeInBytes, err := parseSize(maxSizeStr)
|
||||
if err != nil {
|
||||
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: invalid size: %q", maxSizeStr)
|
||||
return nil, nil, linuxerr.EINVAL
|
||||
|
@ -944,3 +944,33 @@ func (fd *fileDescription) RemoveXattr(ctx context.Context, name string) error {
|
|||
func (*fileDescription) Sync(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseSize converts size in string to an integer bytes.
|
||||
// Supported suffixes in string are:K, M, G, T, P, E.
|
||||
func parseSize(s string) (uint64, error) {
|
||||
suffix := s[len(s)-1]
|
||||
count := 1
|
||||
switch suffix {
|
||||
case 'e', 'E':
|
||||
count = count << 10
|
||||
fallthrough
|
||||
case 'p', 'P':
|
||||
count = count << 10
|
||||
fallthrough
|
||||
case 't', 'T':
|
||||
count = count << 10
|
||||
fallthrough
|
||||
case 'g', 'G':
|
||||
count = count << 10
|
||||
fallthrough
|
||||
case 'm', 'M':
|
||||
count = count << 10
|
||||
fallthrough
|
||||
case 'k', 'K':
|
||||
count = count << 10
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
bytes, err := strconv.ParseUint(s, 10, 64)
|
||||
bytes = bytes * uint64(count)
|
||||
return bytes, err
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ package tmpfs
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
|
@ -155,3 +156,37 @@ func newPipeFD(ctx context.Context, mode linux.FileMode) (*vfs.FileDescription,
|
|||
|
||||
return fd, cleanup, nil
|
||||
}
|
||||
|
||||
func TestParseSize(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s string
|
||||
want uint64
|
||||
wantError bool
|
||||
}{
|
||||
{"500", 500, false},
|
||||
{"5k", (5 * 1024), false},
|
||||
{"5m", (5 * 1024 * 1024), false},
|
||||
{"5G", (5 * 1024 * 1024 * 1024), false},
|
||||
{"5t", (5 * 1024 * 1024 * 1024 * 1024), false},
|
||||
{"5P", (5 * 1024 * 1024 * 1024 * 1024 * 1024), false},
|
||||
{"5e", (5 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024), false},
|
||||
{"5e3", 0, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
testname := fmt.Sprintf("%s", tt.s)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
size, err := parseSize(tt.s)
|
||||
if tt.wantError && err == nil {
|
||||
t.Errorf("Invalid input: %v parsed", tt.s)
|
||||
}
|
||||
if !tt.wantError {
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't parse size, Error: %v", err)
|
||||
}
|
||||
if size != tt.want {
|
||||
t.Errorf("got: %v, want %v", size, tt.want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ const (
|
|||
)
|
||||
|
||||
// tmpfs has some extra supported options that we must pass through.
|
||||
var tmpfsAllowedData = []string{"mode", "uid", "gid"}
|
||||
var tmpfsAllowedData = []string{"mode", "size", "uid", "gid"}
|
||||
|
||||
func addOverlay(ctx context.Context, lower *fs.Inode, name string, lowerFlags fs.MountSourceFlags) (*fs.Inode, error) {
|
||||
// Upper layer uses the same flags as lower, but it must be read-write.
|
||||
|
|
|
@ -911,3 +911,42 @@ func TestRevalidateSymlinkChain(t *testing.T) {
|
|||
t.Fatalf("Read wrong file, want: %q, got: %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTmpMountWithSize checks when 'tmpfs' is mounted
|
||||
// with size option the limit is not exceeded.
|
||||
func TestTmpMountWithSize(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
d := dockerutil.MakeContainer(ctx, t)
|
||||
defer d.CleanUp(ctx)
|
||||
|
||||
opts := dockerutil.RunOpts{
|
||||
Image: "basic/alpine",
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: mount.TypeTmpfs,
|
||||
Target: "/tmp/foo",
|
||||
TmpfsOptions: &mount.TmpfsOptions{
|
||||
SizeBytes: 4096,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := d.Create(ctx, opts, "sleep", "1000"); err != nil {
|
||||
t.Fatalf("docker create failed: %v", err)
|
||||
}
|
||||
if err := d.Start(ctx); err != nil {
|
||||
t.Fatalf("docker start failed: %v", err)
|
||||
}
|
||||
|
||||
if _, err := d.Exec(ctx, dockerutil.ExecOpts{}, "/bin/sh", "-c", "echo hello > /tmp/foo/test1.txt"); err != nil {
|
||||
t.Fatalf("docker exec failed: %v", err)
|
||||
}
|
||||
echoOutput, err := d.Exec(ctx, dockerutil.ExecOpts{}, "/bin/sh", "-c", "echo world > /tmp/foo/test2.txt")
|
||||
if err == nil {
|
||||
t.Fatalf("docker exec size check failed: %v", err)
|
||||
}
|
||||
wantErr := "No space left on device"
|
||||
if !strings.Contains(echoOutput, wantErr) {
|
||||
t.Errorf("unexpected echo error:Expected: %v, Got: %v", wantErr, echoOutput)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue