From 0920a47f25089b2ef01b21fb9b36b4841b5872de Mon Sep 17 00:00:00 2001 From: Roman Vanicek Date: Tue, 19 Mar 2024 22:59:54 +0100 Subject: [PATCH] Allow reduction of mounted snapshots to conserve RAM --- main.go | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index d8338e8..4245fff 100644 --- a/main.go +++ b/main.go @@ -35,12 +35,13 @@ import ( ) type ofsVolume struct { - Volume *volume.Volume - Fs string - Opts string - Env []string - Asap bool - MountSnapshots bool + Volume *volume.Volume + Fs string + Opts string + Env []string + Asap bool + MountSnapshots bool + SnapshotsFilter string } type ofsVolumeRt struct { @@ -104,6 +105,8 @@ func (d *ofsDriver) Create(r *volume.CreateRequest) error { v.Asap = true case "mountSnapshots": v.MountSnapshots = val == "yes" + case "snapshotsFilter": + v.SnapshotsFilter = val default: env[key] = val } @@ -349,20 +352,35 @@ func (d *ofsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) if existingMountDirs, err := getMountedSnaphots(snapshotsPath, false); err == nil { log.WithFields(log.Fields{"name": r.Name, "existingMountDirs": existingMounts}).Trace("Existing snapshot mount dirs") - // Remove left-over dirs of expired snapshots (ie. appears during downtime) - for i, path := range setMinus(setMinus(existingMountDirs, expectedSnapshots), existingMounts) { - if err := os.Remove(path); err != nil { - log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to remove directory of an off-line expired snapshot.") + // PERF: We allow mounting just subset of snapshots for performance reasons (required RAM) + var filteredSnapshots map[string]bool + if len(strings.TrimSpace(v.SnapshotsFilter)) != 0 { + if a, err := generateSnapshotsFromRulesForNow(strings.TrimSpace(v.SnapshotsFilter)); err != nil { + filteredSnapshots = a + log.WithFields(log.Fields{"name": r.Name, "invalidFilter": a}).Trace("Snapshots filter.") + } else { + filteredSnapshots = expectedSnapshots + log.WithFields(log.Fields{"name": r.Name, "invalidFilter": v.SnapshotsFilter}).Warn("Failed to parse snapshots filter. Will mount all snapshots.") } + } else { + filteredSnapshots = expectedSnapshots } - // Remove mounts of expired snapshots - for i, path := range setMinus(existingMounts, expectedSnapshots) { + // Unmount snapshots that are no longer in filteredSnapshots to conserve RAM + // Note: We cannot remove the directory as other machines may have different + // filteredSnapshots and may be using them. + for i, path := range setMinus(existingMounts, setIntersect(expectedSnapshots, filteredSnapshots)) { if err := exec.Command("umount", path).Run(); err != nil { log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to unmount an expired snapshot.") } else { log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Debug("Snapshot unmounted.") } + } + + // Remove left-over dirs of expired snapshots + // Note: That is directories that no other machine would use as the snapshots are not + // mounted due to filteredSnapshots but because they are not even in expectedSnapshots. + for i, path := range setMinus(existingMountDirs, expectedSnapshots) { if err := os.Remove(path); err != nil { log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to remove directory of an expired snapshot.") } @@ -379,7 +397,7 @@ func (d *ofsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) } // Add new mounts - for i, name := range setMinus(setIntersect(existingSnapshots, expectedSnapshots), existingMounts) { + for i, name := range setMinus(setIntersect(existingSnapshots, setIntersect(expectedSnapshots, filteredSnapshots)), existingMounts) { dest := filepath.Join(snapshotsPath, i) if err := os.Mkdir(dest, os.ModePerm); err == nil || os.IsExist(err) { // Note: There is a missing "mount" argument so the mount continues running in a background process