Skip to content

Commit d18bb68

Browse files
committed
Integrate the temporary directory into layer deletion
This enables deferred deletion of physical files outside of global locks, improving performance and reducing lock contention. Signed-off-by: Jan Rodák <[email protected]>
1 parent 894e80c commit d18bb68

File tree

11 files changed

+285
-35
lines changed

11 files changed

+285
-35
lines changed

drivers/aufs/aufs.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"time"
3737

3838
graphdriver "github.com/containers/storage/drivers"
39+
"github.com/containers/storage/internal/tempdir"
3940
"github.com/containers/storage/pkg/archive"
4041
"github.com/containers/storage/pkg/chrootarchive"
4142
"github.com/containers/storage/pkg/directory"
@@ -781,3 +782,14 @@ func (a *Driver) SupportsShifting(uidmap, gidmap []idtools.IDMap) bool {
781782
func (a *Driver) Dedup(req graphdriver.DedupArgs) (graphdriver.DedupResult, error) {
782783
return graphdriver.DedupResult{}, nil
783784
}
785+
786+
// DeferredRemove is not implemented.
787+
// It calls Remove directly.
788+
func (a *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
789+
return nil, a.Remove(id)
790+
}
791+
792+
// GetTempDirRootDir is not implemented.
793+
func (a *Driver) GetTempDirRootDir() string {
794+
return ""
795+
}

drivers/btrfs/btrfs.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"unsafe"
3131

3232
graphdriver "github.com/containers/storage/drivers"
33+
"github.com/containers/storage/internal/tempdir"
3334
"github.com/containers/storage/pkg/directory"
3435
"github.com/containers/storage/pkg/fileutils"
3536
"github.com/containers/storage/pkg/idtools"
@@ -678,3 +679,14 @@ func (d *Driver) AdditionalImageStores() []string {
678679
func (d *Driver) Dedup(req graphdriver.DedupArgs) (graphdriver.DedupResult, error) {
679680
return graphdriver.DedupResult{}, nil
680681
}
682+
683+
// DeferredRemove is not implemented.
684+
// It calls Remove directly.
685+
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
686+
return nil, d.Remove(id)
687+
}
688+
689+
// GetTempDirRootDir is not implemented.
690+
func (d *Driver) GetTempDirRootDir() string {
691+
return ""
692+
}

drivers/driver.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010

1111
"github.com/containers/storage/internal/dedup"
12+
"github.com/containers/storage/internal/tempdir"
1213
"github.com/containers/storage/pkg/archive"
1314
"github.com/containers/storage/pkg/directory"
1415
"github.com/containers/storage/pkg/fileutils"
@@ -124,6 +125,13 @@ type ProtoDriver interface {
124125
CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *CreateOpts, readWrite bool) error
125126
// Remove attempts to remove the filesystem layer with this id.
126127
Remove(id string) error
128+
// DeferredRemove is used to remove the filesystem layer with this id.
129+
// This removal happen immediately (the layer is no longer usable),
130+
// but physically deleting the files may be deferred.
131+
// Caller MUST call returned Cleanup function.
132+
DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error)
133+
// GetTempDirRootDir returns the root directory for temporary directories.
134+
GetTempDirRootDir() string
127135
// Get returns the mountpoint for the layered filesystem referred
128136
// to by this id. You can optionally specify a mountLabel or "".
129137
// Optionally it gets the mappings used to create the layer.

drivers/overlay/overlay.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/containers/storage/drivers/quota"
2525
"github.com/containers/storage/internal/dedup"
2626
"github.com/containers/storage/internal/staging_lockfile"
27+
"github.com/containers/storage/internal/tempdir"
2728
"github.com/containers/storage/pkg/archive"
2829
"github.com/containers/storage/pkg/chrootarchive"
2930
"github.com/containers/storage/pkg/directory"
@@ -1327,6 +1328,39 @@ func (d *Driver) Remove(id string) error {
13271328
return nil
13281329
}
13291330

1331+
func (d *Driver) GetTempDirRootDir() string {
1332+
return filepath.Join(d.home, stagingDir)
1333+
}
1334+
1335+
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
1336+
t, err := tempdir.NewTempDir(d.GetTempDirRootDir())
1337+
if err != nil {
1338+
return nil, err
1339+
}
1340+
1341+
dir := d.dir(id)
1342+
lid, err := os.ReadFile(path.Join(dir, "link"))
1343+
if err == nil {
1344+
if err := t.Add(path.Join(d.home, linkDir, string(lid))); err != nil {
1345+
logrus.Debugf("Failed to Add to stage Directory link: %v", err)
1346+
}
1347+
}
1348+
1349+
d.releaseAdditionalLayerByID(id)
1350+
1351+
if err := t.Add(dir); err != nil {
1352+
return t.Cleanup, fmt.Errorf("failed to add to stage directory: %w", err)
1353+
}
1354+
1355+
if d.quotaCtl != nil {
1356+
d.quotaCtl.ClearQuota(dir)
1357+
if d.imageStore != "" {
1358+
d.quotaCtl.ClearQuota(d.imageStore)
1359+
}
1360+
}
1361+
return t.Cleanup, nil
1362+
}
1363+
13301364
// recreateSymlinks goes through the driver's home directory and checks if the diff directory
13311365
// under each layer has a symlink created for it under the linkDir. If the symlink does not
13321366
// exist, it creates them
@@ -1353,8 +1387,8 @@ func (d *Driver) recreateSymlinks() error {
13531387
// Check that for each layer, there's a link in "l" with the name in
13541388
// the layer's "link" file that points to the layer's "diff" directory.
13551389
for _, dir := range dirs {
1356-
// Skip over the linkDir and anything that is not a directory
1357-
if dir.Name() == linkDir || !dir.IsDir() {
1390+
// Skip over the linkDir and anything that is not a directory or tempDir
1391+
if dir.Name() == linkDir || !dir.IsDir() || dir.Name() == stagingDir {
13581392
continue
13591393
}
13601394
// Read the "link" file under each layer to get the name of the symlink

drivers/vfs/driver.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
graphdriver "github.com/containers/storage/drivers"
1313
"github.com/containers/storage/internal/dedup"
14+
"github.com/containers/storage/internal/tempdir"
1415
"github.com/containers/storage/pkg/archive"
1516
"github.com/containers/storage/pkg/directory"
1617
"github.com/containers/storage/pkg/fileutils"
@@ -244,6 +245,21 @@ func (d *Driver) Remove(id string) error {
244245
return system.EnsureRemoveAll(d.dir(id))
245246
}
246247

248+
func (d *Driver) GetTempDirRootDir() string {
249+
return filepath.Join(d.home, "tempdirs")
250+
}
251+
252+
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
253+
t, err := tempdir.NewTempDir(d.GetTempDirRootDir())
254+
if err != nil {
255+
return nil, err
256+
}
257+
if err := t.Add(d.dir(id)); err != nil {
258+
return nil, err
259+
}
260+
return t.Cleanup, nil
261+
}
262+
247263
// Get returns the directory for the given id.
248264
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
249265
dir := d.dir(id)

drivers/windows/windows.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/Microsoft/go-winio/backuptar"
2525
"github.com/Microsoft/hcsshim"
2626
graphdriver "github.com/containers/storage/drivers"
27+
"github.com/containers/storage/internal/tempdir"
2728
"github.com/containers/storage/pkg/archive"
2829
"github.com/containers/storage/pkg/directory"
2930
"github.com/containers/storage/pkg/fileutils"
@@ -1014,3 +1015,14 @@ func parseStorageOpt(storageOpt map[string]string) (*storageOptions, error) {
10141015
}
10151016
return &options, nil
10161017
}
1018+
1019+
// DeferredRemove is not implemented.
1020+
// It calls Remove directly.
1021+
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
1022+
return nil, d.Remove(id)
1023+
}
1024+
1025+
// GetTempDirRootDir is not implemented.
1026+
func (d *Driver) GetTempDirRootDir() string {
1027+
return ""
1028+
}

drivers/zfs/zfs.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
graphdriver "github.com/containers/storage/drivers"
16+
"github.com/containers/storage/internal/tempdir"
1617
"github.com/containers/storage/pkg/directory"
1718
"github.com/containers/storage/pkg/idtools"
1819
"github.com/containers/storage/pkg/mount"
@@ -406,6 +407,12 @@ func (d *Driver) Remove(id string) error {
406407
return nil
407408
}
408409

410+
// DeferredRemove is not implemented.
411+
// It calls Remove directly.
412+
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
413+
return nil, d.Remove(id)
414+
}
415+
409416
// Get returns the mountpoint for the given id after creating the target directories if necessary.
410417
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
411418
mountpoint := d.mountPath(id)
@@ -516,3 +523,8 @@ func (d *Driver) AdditionalImageStores() []string {
516523
func (d *Driver) Dedup(req graphdriver.DedupArgs) (graphdriver.DedupResult, error) {
517524
return graphdriver.DedupResult{}, nil
518525
}
526+
527+
// GetTempDirRootDir is not implemented.
528+
func (d *Driver) GetTempDirRootDir() string {
529+
return ""
530+
}

0 commit comments

Comments
 (0)