Skip to content

Commit 8f3673c

Browse files
authored
Merge pull request #314 from BigVan/main
[feat.] AsyncRemove support
2 parents 657a32f + 585f307 commit 8f3673c

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed

cmd/overlaybd-snapshotter/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ func parseConfig(fpath string) error {
5151
if err := json.Unmarshal(data, pconfig); err != nil {
5252
return errors.Wrapf(err, "failed to parse plugin config from %s", string(data))
5353
}
54-
logrus.Infof("snapshotter commitID: %s, rwMode: %s, autoRemove: %v, writableLayerType: %s",
55-
commitID, pconfig.RwMode, pconfig.AutoRemoveDev, pconfig.WritableLayerType)
54+
logrus.Infof("snapshotter commitID: %s, rwMode: %s, autoRemove: %v, writableLayerType: %s, asyncRemoveSnapshot: %v",
55+
commitID, pconfig.RwMode, pconfig.AutoRemoveDev, pconfig.WritableLayerType, pconfig.AsyncRemove)
5656
return nil
5757
}
5858

docs/PROMETHEUS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ To configure overlaybd as a Prometheus target, you need to specify `uriPrefix` a
99
```json
1010
{
1111
"root": "/var/lib/containerd/io.containerd.snapshotter.v1.overlaybd",
12+
"asyncRemove": false,
1213
"address": "/run/overlaybd-snapshotter/overlaybd.sock",
1314
"verbose": "info",
1415
"rwMode": "overlayfs",

pkg/snapshot/overlay.go

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type Registry struct {
8585
}
8686

8787
type BootConfig struct {
88+
AsyncRemove bool `json:"asyncRemove"`
8889
Address string `json:"address"`
8990
Root string `json:"root"`
9091
LogLevel string `json:"verbose"`
@@ -102,6 +103,7 @@ type BootConfig struct {
102103

103104
func DefaultBootConfig() *BootConfig {
104105
return &BootConfig{
106+
AsyncRemove: false,
105107
LogLevel: "info",
106108
RwMode: "overlayfs",
107109
LogReportCaller: false,
@@ -142,6 +144,15 @@ var defaultConfig = SnapshotterConfig{
142144
// Opt is an option to configure the snapshotter
143145
type Opt func(config *SnapshotterConfig) error
144146

147+
// AsynchronousRemove defers removal of filesystem content until
148+
// the Cleanup method is called. Removals will make the snapshot
149+
// referred to by the key unavailable and make the key immediately
150+
// available for re-use.
151+
func AsynchronousRemove(config *BootConfig) error {
152+
config.AsyncRemove = true
153+
return nil
154+
}
155+
145156
// snapshotter is implementation of github.com/containerd/containerd/snapshots.Snapshotter.
146157
//
147158
// It is a snapshotter plugin. The layout of root dir is organized:
@@ -189,6 +200,7 @@ type snapshotter struct {
189200
tenant int
190201
locker *locker.Locker
191202
turboFsType []string
203+
asyncRemove bool
192204

193205
quotaDriver *diskquota.PrjQuotaDriver
194206
quotaSize string
@@ -256,6 +268,7 @@ func NewSnapshotter(bootConfig *BootConfig, opts ...Opt) (snapshots.Snapshotter,
256268
quotaDriver: &diskquota.PrjQuotaDriver{
257269
QuotaIDs: make(map[uint32]struct{}),
258270
},
271+
asyncRemove: bootConfig.AsyncRemove,
259272
}, nil
260273
}
261274

@@ -910,6 +923,63 @@ func (o *snapshotter) commit(ctx context.Context, name, key string, opts ...snap
910923
return id, info, nil
911924
}
912925

926+
func (o *snapshotter) cleanupDirectories(ctx context.Context) ([]string, error) {
927+
// Get a write transaction to ensure no other write transaction can be entered
928+
// while the cleanup is scanning.
929+
ctx, t, err := o.ms.TransactionContext(ctx, true)
930+
if err != nil {
931+
return nil, err
932+
}
933+
934+
defer t.Rollback()
935+
return o.getCleanupDirectories(ctx, t)
936+
}
937+
func (o *snapshotter) getCleanupDirectories(ctx context.Context, t storage.Transactor) ([]string, error) {
938+
ids, err := storage.IDMap(ctx)
939+
if err != nil {
940+
return nil, err
941+
}
942+
943+
snapshotDir := filepath.Join(o.root, "snapshots")
944+
fd, err := os.Open(snapshotDir)
945+
if err != nil {
946+
return nil, err
947+
}
948+
defer fd.Close()
949+
950+
dirs, err := fd.Readdirnames(0)
951+
if err != nil {
952+
return nil, err
953+
}
954+
955+
cleanup := []string{}
956+
for _, d := range dirs {
957+
if _, ok := ids[d]; ok {
958+
continue
959+
}
960+
961+
cleanup = append(cleanup, filepath.Join(snapshotDir, d))
962+
}
963+
964+
return cleanup, nil
965+
}
966+
967+
// Cleanup cleans up disk resources from removed or abandoned snapshots// Cleanup cleans up disk resources from removed or abandoned snapshots
968+
func (o *snapshotter) Cleanup(ctx context.Context) error {
969+
cleanup, err := o.cleanupDirectories(ctx)
970+
if err != nil {
971+
return err
972+
}
973+
974+
for _, dir := range cleanup {
975+
if err := os.RemoveAll(dir); err != nil {
976+
log.G(ctx).WithError(err).WithField("path", dir).Warn("failed to remove directory")
977+
}
978+
}
979+
980+
return nil
981+
}
982+
913983
// Remove abandons the snapshot identified by key. The snapshot will
914984
// immediately become unavailable and unrecoverable.
915985
func (o *snapshotter) Remove(ctx context.Context, key string) (err error) {
@@ -988,9 +1058,23 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) {
9881058
if err != nil {
9891059
return errors.Wrap(err, "failed to remove")
9901060
}
991-
992-
if err := os.RemoveAll(o.snPath(id)); err != nil && !os.IsNotExist(err) {
993-
return err
1061+
if !o.asyncRemove {
1062+
var removals []string
1063+
removals, err = o.getCleanupDirectories(ctx, t)
1064+
if err != nil {
1065+
return errors.Wrap(err, "unable to get directories for removal")
1066+
}
1067+
defer func() {
1068+
if err == nil {
1069+
for _, dir := range removals {
1070+
if err := os.RemoveAll(dir); err != nil {
1071+
log.G(ctx).WithError(err).WithField("path", dir).Warn("failed to remove directory")
1072+
}
1073+
}
1074+
}
1075+
}()
1076+
} else {
1077+
log.G(ctx).Info("asyncRemove enabled, remove snapshots in Cleanup() method.")
9941078
}
9951079

9961080
rollback = false

0 commit comments

Comments
 (0)