@@ -14,7 +14,7 @@ import (
1414
1515 "github.com/docker/distribution"
1616 "github.com/docker/docker/pkg/ioutils"
17- "github.com/opencontainers/go-digest"
17+ digest "github.com/opencontainers/go-digest"
1818 "github.com/pkg/errors"
1919 "github.com/sirupsen/logrus"
2020)
@@ -305,6 +305,55 @@ func (fms *fileMetadataStore) GetMountParent(mount string) (ChainID, error) {
305305 return ChainID (dgst ), nil
306306}
307307
308+ func (fms * fileMetadataStore ) getOrphan () ([]roLayer , error ) {
309+ var orphanLayers []roLayer
310+ for _ , algorithm := range supportedAlgorithms {
311+ fileInfos , err := ioutil .ReadDir (filepath .Join (fms .root , string (algorithm )))
312+ if err != nil {
313+ if os .IsNotExist (err ) {
314+ continue
315+ }
316+ return nil , err
317+ }
318+
319+ for _ , fi := range fileInfos {
320+ if ! fi .IsDir () || ! strings .HasSuffix (fi .Name (), "-removing" ) {
321+ continue
322+ }
323+ // At this stage, fi.Name value looks like <digest>-<random>-removing
324+ // Split on '-' to get the digest value.
325+ nameSplit := strings .Split (fi .Name (), "-" )
326+ dgst := digest .NewDigestFromEncoded (algorithm , nameSplit [0 ])
327+ if err := dgst .Validate (); err != nil {
328+ logrus .WithError (err ).WithField ("digest" , string (algorithm )+ ":" + nameSplit [0 ]).Debug ("ignoring invalid digest" )
329+ continue
330+ }
331+
332+ chainFile := filepath .Join (fms .root , string (algorithm ), fi .Name (), "cache-id" )
333+ contentBytes , err := ioutil .ReadFile (chainFile )
334+ if err != nil {
335+ if ! os .IsNotExist (err ) {
336+ logrus .WithError (err ).WithField ("digest" , dgst ).Error ("failed to read cache ID" )
337+ }
338+ continue
339+ }
340+ cacheID := strings .TrimSpace (string (contentBytes ))
341+ if cacheID == "" {
342+ logrus .Error ("invalid cache ID" )
343+ continue
344+ }
345+
346+ l := & roLayer {
347+ chainID : ChainID (dgst ),
348+ cacheID : cacheID ,
349+ }
350+ orphanLayers = append (orphanLayers , * l )
351+ }
352+ }
353+
354+ return orphanLayers , nil
355+ }
356+
308357func (fms * fileMetadataStore ) List () ([]ChainID , []string , error ) {
309358 var ids []ChainID
310359 for _ , algorithm := range supportedAlgorithms {
@@ -346,8 +395,39 @@ func (fms *fileMetadataStore) List() ([]ChainID, []string, error) {
346395 return ids , mounts , nil
347396}
348397
349- func (fms * fileMetadataStore ) Remove (layer ChainID ) error {
350- return os .RemoveAll (fms .getLayerDirectory (layer ))
398+ // Remove layerdb folder if that is marked for removal
399+ func (fms * fileMetadataStore ) Remove (layer ChainID , cache string ) error {
400+ dgst := digest .Digest (layer )
401+ files , err := ioutil .ReadDir (filepath .Join (fms .root , string (dgst .Algorithm ())))
402+ if err != nil {
403+ return err
404+ }
405+ for _ , f := range files {
406+ if ! strings .HasSuffix (f .Name (), "-removing" ) || ! strings .HasPrefix (f .Name (), dgst .String ()) {
407+ continue
408+ }
409+
410+ // Make sure that we only remove layerdb folder which points to
411+ // requested cacheID
412+ dir := filepath .Join (fms .root , string (dgst .Algorithm ()), f .Name ())
413+ chainFile := filepath .Join (dir , "cache-id" )
414+ contentBytes , err := ioutil .ReadFile (chainFile )
415+ if err != nil {
416+ logrus .WithError (err ).WithField ("file" , chainFile ).Error ("cannot get cache ID" )
417+ continue
418+ }
419+ cacheID := strings .TrimSpace (string (contentBytes ))
420+ if cacheID != cache {
421+ continue
422+ }
423+ logrus .Debugf ("Removing folder: %s" , dir )
424+ err = os .RemoveAll (dir )
425+ if err != nil && ! os .IsNotExist (err ) {
426+ logrus .WithError (err ).WithField ("name" , f .Name ()).Error ("cannot remove layer" )
427+ continue
428+ }
429+ }
430+ return nil
351431}
352432
353433func (fms * fileMetadataStore ) RemoveMount (mount string ) error {
0 commit comments