containerd/plugins/snapshots/blockfile/blockfile_loopsetup_test.go
Derek McGowan 2909f07f85
Move snapshots/blockfile to plugins/snapshots/blockfile
Signed-off-by: Derek McGowan <derek@mcg.dev>
2024-01-17 09:53:06 -08:00

128 lines
3.2 KiB
Go

//go:build !windows && !darwin
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package blockfile
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/containerd/containerd/v2/core/mount"
)
func setupSnapshotter(t *testing.T) ([]Opt, error) {
mkfs, err := exec.LookPath("mkfs.ext4")
if err != nil {
t.Skipf("Could not find mkfs.ext4: %v", err)
}
loopbackSize := int64(8 << 20) // 8 MB
if os.Getpagesize() > 4096 {
loopbackSize = int64(16 << 20) // 16 MB
}
scratch := filepath.Join(t.TempDir(), "scratch")
scratchDevFile, err := os.OpenFile(scratch, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
return nil, fmt.Errorf("failed to create %s: %w", scratch, err)
}
if err := scratchDevFile.Truncate(loopbackSize); err != nil {
scratchDevFile.Close()
return nil, fmt.Errorf("failed to resize %s file: %w", scratch, err)
}
if err := scratchDevFile.Sync(); err != nil {
scratchDevFile.Close()
return nil, fmt.Errorf("failed to sync %s file: %w", scratch, err)
}
scratchDevFile.Close()
if out, err := exec.Command(mkfs, scratch).CombinedOutput(); err != nil {
return nil, fmt.Errorf("failed to make ext4 filesystem (out: %q): %w", out, err)
}
defaultOpts := []string{"loop", "direct-io", "sync"}
if err := testMount(t, scratch, defaultOpts); err != nil {
return nil, err
}
return []Opt{
WithScratchFile(scratch),
WithFSType("ext4"),
WithMountOptions(defaultOpts),
WithRecreateScratch(false), // reduce IO presure in CI
withViewHookHelper(testViewHook),
}, nil
}
func testMount(t *testing.T, scratchFile string, opts []string) error {
root, err := os.MkdirTemp(t.TempDir(), "")
if err != nil {
return err
}
defer os.RemoveAll(root)
m := []mount.Mount{
{
Type: "ext4",
Source: scratchFile,
Options: opts,
},
}
if err := mount.All(m, root); err != nil {
return fmt.Errorf("failed to mount device %s: %w", scratchFile, err)
}
if err := os.Remove(filepath.Join(root, "lost+found")); err != nil {
return err
}
return mount.UnmountAll(root, 0)
}
func testViewHook(backingFile string, fsType string, defaultOpts []string) error {
root, err := os.MkdirTemp("", "blockfile-testViewHook-XXXX")
if err != nil {
return err
}
defer os.RemoveAll(root)
// FIXME(fuweid): Mount with rw to force fs to handle recover
mountOpts := []mount.Mount{
{
Type: fsType,
Source: backingFile,
Options: defaultOpts,
},
}
if err := mount.All(mountOpts, root); err != nil {
return fmt.Errorf("failed to mount device %s: %w", backingFile, err)
}
if err := mount.UnmountAll(root, 0); err != nil {
return fmt.Errorf("failed to unmount device %s: %w", backingFile, err)
}
return nil
}