summaryrefslogtreecommitdiff
path: root/layer/filestore.go
diff options
context:
space:
mode:
authorOlli Janatuinen <olli.janatuinen@gmail.com>2019-05-08 04:27:15 +0300
committerOlli Janatuinen <olli.janatuinen@gmail.com>2019-06-05 22:02:42 +0300
commit213681b66a41d7728445e30125176834ce349c2a (patch)
tree9d4b90d1bf2a9f079eb91b953fbc7cea55195917 /layer/filestore.go
parent71e00574c750cb7bbec17af32dbad9e68b96ec14 (diff)
downloaddocker-213681b66a41d7728445e30125176834ce349c2a.tar.gz
First step to implement full garbage collector for image layers
Refactored exiting logic on way that layers are first marked to be under removal so if actual removal fails they can be found from disk and cleaned up. Full garbage collector will be implemented as part of containerd migration. Signed-off-by: Olli Janatuinen <olli.janatuinen@gmail.com>
Diffstat (limited to 'layer/filestore.go')
-rw-r--r--layer/filestore.go76
1 files changed, 74 insertions, 2 deletions
diff --git a/layer/filestore.go b/layer/filestore.go
index 208a0c3a85..37a927022a 100644
--- a/layer/filestore.go
+++ b/layer/filestore.go
@@ -305,6 +305,47 @@ func (fms *fileMetadataStore) GetMountParent(mount string) (ChainID, error) {
return ChainID(dgst), nil
}
+func (fms *fileMetadataStore) getOrphan() ([]roLayer, error) {
+ var orphanLayers []roLayer
+ for _, algorithm := range supportedAlgorithms {
+ fileInfos, err := ioutil.ReadDir(filepath.Join(fms.root, string(algorithm)))
+ if err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+
+ for _, fi := range fileInfos {
+ if fi.IsDir() && strings.Contains(fi.Name(), "-removing") {
+ nameSplit := strings.Split(fi.Name(), "-")
+ dgst := digest.NewDigestFromEncoded(algorithm, nameSplit[0])
+ if err := dgst.Validate(); err != nil {
+ logrus.Debugf("Ignoring invalid digest %s:%s", algorithm, nameSplit[0])
+ } else {
+ chainID := ChainID(dgst)
+ chainFile := filepath.Join(fms.root, string(algorithm), fi.Name(), "cache-id")
+ contentBytes, err := ioutil.ReadFile(chainFile)
+ if err != nil {
+ logrus.WithError(err).WithField("digest", dgst).Error("cannot get cache ID")
+ }
+ cacheID := strings.TrimSpace(string(contentBytes))
+ if cacheID == "" {
+ logrus.Errorf("invalid cache id value")
+ }
+
+ l := &roLayer{
+ chainID: chainID,
+ cacheID: cacheID,
+ }
+ orphanLayers = append(orphanLayers, *l)
+ }
+ }
+ }
+ }
+ return orphanLayers, nil
+}
+
func (fms *fileMetadataStore) List() ([]ChainID, []string, error) {
var ids []ChainID
for _, algorithm := range supportedAlgorithms {
@@ -346,8 +387,39 @@ func (fms *fileMetadataStore) List() ([]ChainID, []string, error) {
return ids, mounts, nil
}
-func (fms *fileMetadataStore) Remove(layer ChainID) error {
- return os.RemoveAll(fms.getLayerDirectory(layer))
+// Remove layerdb folder if that is marked for removal
+func (fms *fileMetadataStore) Remove(layer ChainID, cache string) error {
+ dgst := digest.Digest(layer)
+ files, err := ioutil.ReadDir(filepath.Join(fms.root, string(dgst.Algorithm())))
+ if err != nil {
+ return err
+ }
+ for _, f := range files {
+ if !strings.HasSuffix(f.Name(), "-removing") || !strings.HasPrefix(f.Name(), dgst.String()) {
+ continue
+ }
+
+ // Make sure that we only remove layerdb folder which points to
+ // requested cacheID
+ dir := filepath.Join(fms.root, string(dgst.Algorithm()), f.Name())
+ chainFile := filepath.Join(dir, "cache-id")
+ contentBytes, err := ioutil.ReadFile(chainFile)
+ if err != nil {
+ logrus.WithError(err).WithField("file", chainFile).Error("cannot get cache ID")
+ continue
+ }
+ cacheID := strings.TrimSpace(string(contentBytes))
+ if cacheID != cache {
+ continue
+ }
+ logrus.Debugf("Removing folder: %s", dir)
+ err = os.RemoveAll(dir)
+ if err != nil && !os.IsNotExist(err) {
+ logrus.WithError(err).WithField("name", f.Name()).Error("cannot remove layer")
+ continue
+ }
+ }
+ return nil
}
func (fms *fileMetadataStore) RemoveMount(mount string) error {