Mount devmapper xfs file system with "nouuid" option.
Two xfs file systems with same UUID can not be mounted on the same system. However devmapper snapshots will have same UUID as original filesystem. This patch fixes the bug by mounting a xfs file system with "nouuid" option. Signed-off-by: Henry Wang <henwang@amazon.com>
This commit is contained in:
parent
b521429b67
commit
0d0b2bd4fe
@ -504,6 +504,8 @@ func (s *Snapshotter) buildMounts(ctx context.Context, snap storage.Snapshot, fi
|
|||||||
if fileSystemType == "" {
|
if fileSystemType == "" {
|
||||||
log.G(ctx).Error("File system type cannot be empty")
|
log.G(ctx).Error("File system type cannot be empty")
|
||||||
return nil
|
return nil
|
||||||
|
} else if fileSystemType == fsTypeXFS {
|
||||||
|
options = append(options, "nouuid")
|
||||||
}
|
}
|
||||||
if snap.Kind != snapshots.KindActive {
|
if snap.Kind != snapshots.KindActive {
|
||||||
options = append(options, "ro")
|
options = append(options, "ro")
|
||||||
|
@ -46,38 +46,13 @@ func TestSnapshotterSuite(t *testing.T) {
|
|||||||
logrus.SetLevel(logrus.DebugLevel)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
|
|
||||||
snapshotterFn := func(ctx context.Context, root string) (snapshots.Snapshotter, func() error, error) {
|
snapshotterFn := func(ctx context.Context, root string) (snapshots.Snapshotter, func() error, error) {
|
||||||
// Create loopback devices for each test case
|
|
||||||
_, loopDataDevice := createLoopbackDevice(t, root)
|
|
||||||
_, loopMetaDevice := createLoopbackDevice(t, root)
|
|
||||||
|
|
||||||
poolName := fmt.Sprintf("containerd-snapshotter-suite-pool-%d", time.Now().Nanosecond())
|
poolName := fmt.Sprintf("containerd-snapshotter-suite-pool-%d", time.Now().Nanosecond())
|
||||||
err := dmsetup.CreatePool(poolName, loopDataDevice, loopMetaDevice, 64*1024/dmsetup.SectorSize)
|
|
||||||
assert.NilError(t, err, "failed to create pool %q", poolName)
|
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
RootPath: root,
|
RootPath: root,
|
||||||
PoolName: poolName,
|
PoolName: poolName,
|
||||||
BaseImageSize: "16Mb",
|
BaseImageSize: "16Mb",
|
||||||
}
|
}
|
||||||
|
return createSnapshotter(ctx, t, config)
|
||||||
snap, err := NewSnapshotter(context.Background(), config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove device mapper pool and detach loop devices after test completes
|
|
||||||
removePool := func() error {
|
|
||||||
result := multierror.Append(
|
|
||||||
snap.pool.RemovePool(ctx),
|
|
||||||
mount.DetachLoopDevice(loopDataDevice, loopMetaDevice))
|
|
||||||
|
|
||||||
return result.ErrorOrNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pool cleanup should be called before closing metadata store (as we need to retrieve device names)
|
|
||||||
snap.cleanupFn = append([]closeFunc{removePool}, snap.cleanupFn...)
|
|
||||||
|
|
||||||
return snap, snap.Close, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testsuite.SnapshotterSuite(t, "devmapper", snapshotterFn)
|
testsuite.SnapshotterSuite(t, "devmapper", snapshotterFn)
|
||||||
@ -165,3 +140,85 @@ func TestMkfsXfsNonDefault(t *testing.T) {
|
|||||||
err := mkfs(ctx, "xfs", "noquota", "")
|
err := mkfs(ctx, "xfs", "noquota", "")
|
||||||
assert.ErrorContains(t, err, `mkfs.xfs couldn't initialize ""`)
|
assert.ErrorContains(t, err, `mkfs.xfs couldn't initialize ""`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMultipleXfsMounts(t *testing.T) {
|
||||||
|
testutil.RequiresRoot(t)
|
||||||
|
|
||||||
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx = namespaces.WithNamespace(ctx, "testsuite")
|
||||||
|
tempDir, err := os.MkdirTemp("", "snapshot-suite-usage")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
poolName := fmt.Sprintf("containerd-snapshotter-suite-pool-%d", time.Now().Nanosecond())
|
||||||
|
config := &Config{
|
||||||
|
RootPath: tempDir,
|
||||||
|
PoolName: poolName,
|
||||||
|
BaseImageSize: "16Mb",
|
||||||
|
FileSystemType: "xfs",
|
||||||
|
}
|
||||||
|
snapshotter, closer, err := createSnapshotter(ctx, t, config)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
var (
|
||||||
|
sizeBytes int64 = 1048576 // 1MB
|
||||||
|
baseApplier = fstest.Apply(fstest.CreateRandomFile("/a", 12345679, sizeBytes, 0777))
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create base layer
|
||||||
|
mounts, err := snapshotter.Prepare(ctx, "prepare-1", "")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
root1, _ := os.MkdirTemp(os.TempDir(), "containerd-mount")
|
||||||
|
defer func() {
|
||||||
|
mount.UnmountAll(root1, 0)
|
||||||
|
os.Remove(root1)
|
||||||
|
}()
|
||||||
|
err = mount.All(mounts, root1)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
baseApplier.Apply(root1)
|
||||||
|
snapshotter.Commit(ctx, "layer-1", "prepare-1")
|
||||||
|
|
||||||
|
// Create one child layer
|
||||||
|
mounts, err = snapshotter.Prepare(ctx, "prepare-2", "layer-1")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
root2, _ := os.MkdirTemp(os.TempDir(), "containerd-mount")
|
||||||
|
defer func() {
|
||||||
|
mount.UnmountAll(root2, 0)
|
||||||
|
os.Remove(root2)
|
||||||
|
}()
|
||||||
|
err = mount.All(mounts, root2)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSnapshotter(ctx context.Context, t *testing.T, config *Config) (snapshots.Snapshotter, func() error, error) {
|
||||||
|
// Create loopback devices for each test case
|
||||||
|
_, loopDataDevice := createLoopbackDevice(t, config.RootPath)
|
||||||
|
_, loopMetaDevice := createLoopbackDevice(t, config.RootPath)
|
||||||
|
|
||||||
|
err := dmsetup.CreatePool(config.PoolName, loopDataDevice, loopMetaDevice, 64*1024/dmsetup.SectorSize)
|
||||||
|
assert.NilError(t, err, "failed to create pool %q", config.PoolName)
|
||||||
|
|
||||||
|
snap, err := NewSnapshotter(ctx, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove device mapper pool and detach loop devices after test completes
|
||||||
|
removePool := func() error {
|
||||||
|
result := multierror.Append(
|
||||||
|
snap.pool.RemovePool(ctx),
|
||||||
|
mount.DetachLoopDevice(loopDataDevice, loopMetaDevice))
|
||||||
|
|
||||||
|
return result.ErrorOrNil()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool cleanup should be called before closing metadata store (as we need to retrieve device names)
|
||||||
|
snap.cleanupFn = append([]closeFunc{removePool}, snap.cleanupFn...)
|
||||||
|
|
||||||
|
return snap, snap.Close, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user