diff --git a/pkg/snapshotter/btrfs.go b/pkg/snapshotter/btrfs.go index 1cb21166cac..01b026b9295 100644 --- a/pkg/snapshotter/btrfs.go +++ b/pkg/snapshotter/btrfs.go @@ -68,6 +68,7 @@ type Btrfs struct { installing bool snapperArgs []string snapshotsUmount func() error + snapshotsMount func() error } type btrfsSubvol struct { @@ -130,6 +131,7 @@ func newBtrfsSnapshotter(cfg types.Config, snapCfg types.SnapshotterConfig, boot return &Btrfs{ cfg: cfg, snapshotterCfg: snapCfg, btrfsCfg: *btrfsCfg, bootloader: bootloader, snapshotsUmount: func() error { return nil }, + snapshotsMount: func() error { return nil }, }, nil } @@ -381,17 +383,34 @@ func (b *Btrfs) DeleteSnapshot(id int) error { return nil } -func (b *Btrfs) GetSnapshots() ([]int, error) { - if ok, err := b.isInitiated(b.rootDir); ok { - snapshots, err := b.loadSnapshots() +func (b *Btrfs) GetSnapshots() (snapshots []int, err error) { + var ok bool + + if ok, err = b.isInitiated(b.rootDir); ok { + // Check if snapshots subvolume is mounted + snapshotsSubolume := filepath.Join(b.rootDir, fmt.Sprintf(snapshotPathTmpl, b.activeSnapshotID), snapshotsPath) + if notMnt, _ := b.cfg.Mounter.IsLikelyNotMountPoint(snapshotsSubolume); notMnt { + err = b.snapshotsMount() + if err != nil { + return nil, err + } + defer func() { + nErr := b.snapshotsUmount() + if err == nil && nErr != nil { + err = nErr + snapshots = nil + } + }() + } + snapshots, err = b.loadSnapshots() if err != nil { return nil, err } - return snapshots, nil + return snapshots, err } else if err != nil { return nil, err } - return []int{}, nil + return []int{}, err } func (b *Btrfs) loadSnapshots() ([]int, error) { @@ -695,10 +714,15 @@ func (b *Btrfs) remountStatePartition(state *types.Partition) error { } func (b *Btrfs) mountSnapshotsSubvolumeInSnapshot(root, device string, snapshotID int) error { - b.cfg.Logger.Debugf("Mount snapshots subvolume in active snapshot %d", snapshotID) - mountpoint := filepath.Join(filepath.Join(root, fmt.Sprintf(snapshotPathTmpl, snapshotID)), snapshotsPath) - subvol := fmt.Sprintf("subvol=%s", filepath.Join(rootSubvol, snapshotsPath)) - err := b.cfg.Mounter.Mount(device, mountpoint, "btrfs", []string{"rw", subvol}) + var mountpoint, subvol string + + b.snapshotsMount = func() error { + b.cfg.Logger.Debugf("Mount snapshots subvolume in active snapshot %d", snapshotID) + mountpoint = filepath.Join(filepath.Join(root, fmt.Sprintf(snapshotPathTmpl, snapshotID)), snapshotsPath) + subvol = fmt.Sprintf("subvol=%s", filepath.Join(rootSubvol, snapshotsPath)) + return b.cfg.Mounter.Mount(device, mountpoint, "btrfs", []string{"rw", subvol}) + } + err := b.snapshotsMount() if err != nil { b.cfg.Logger.Errorf("failed mounting subvolume %s at %s", subvol, mountpoint) return err