github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/rkt/image_gc.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "fmt" 19 20 "github.com/coreos/rkt/Godeps/_workspace/src/github.com/spf13/cobra" 21 "github.com/coreos/rkt/common" 22 "github.com/coreos/rkt/pkg/lock" 23 "github.com/coreos/rkt/store" 24 ) 25 26 var ( 27 cmdImageGc = &cobra.Command{ 28 Use: "gc", 29 Short: "Garbage collect local store", 30 Run: runWrapper(runGcImage), 31 } 32 ) 33 34 func init() { 35 cmdImage.AddCommand(cmdImageGc) 36 } 37 38 func runGcImage(cmd *cobra.Command, args []string) (exit int) { 39 s, err := store.NewStore(globalFlags.Dir) 40 if err != nil { 41 stderr("rkt: cannot open store: %v", err) 42 return 1 43 } 44 45 if err := gcTreeStore(s); err != nil { 46 stderr("rkt: failed to remove unreferenced treestores: %v", err) 47 return 1 48 } 49 return 0 50 } 51 52 // gcTreeStore removes all treeStoreIDs not referenced by any non garbage 53 // collected pod from the store. 54 func gcTreeStore(s *store.Store) error { 55 // Take an exclusive lock to block other pods being created. 56 // This is needed to avoid races between the below steps (getting the 57 // list of referenced treeStoreIDs, getting the list of treeStoreIDs 58 // from the store, removal of unreferenced treeStoreIDs) and new 59 // pods/treeStores being created/referenced 60 keyLock, err := lock.ExclusiveKeyLock(lockDir(), common.PrepareLock) 61 if err != nil { 62 return fmt.Errorf("cannot get exclusive prepare lock: %v", err) 63 } 64 defer keyLock.Close() 65 referencedTreeStoreIDs, err := getReferencedTreeStoreIDs() 66 if err != nil { 67 return fmt.Errorf("cannot get referenced treestoreIDs: %v", err) 68 } 69 treeStoreIDs, err := s.GetTreeStoreIDs() 70 if err != nil { 71 return fmt.Errorf("cannot get treestoreIDs from the store: %v", err) 72 } 73 for _, treeStoreID := range treeStoreIDs { 74 if _, ok := referencedTreeStoreIDs[treeStoreID]; !ok { 75 if err := s.RemoveTreeStore(treeStoreID); err != nil { 76 stderr("rkt: error removing treestore %q: %v", treeStoreID, err) 77 } else { 78 stderr("rkt: removed treestore %q", treeStoreID) 79 } 80 } 81 } 82 return nil 83 } 84 85 func getReferencedTreeStoreIDs() (map[string]struct{}, error) { 86 treeStoreIDs := map[string]struct{}{} 87 var walkErr error 88 // Consider pods in preparing, prepared, run, exitedgarbage state 89 if err := walkPods(includeMostDirs, func(p *pod) { 90 stage1TreeStoreID, err := p.getStage1TreeStoreID() 91 if err != nil { 92 walkErr = fmt.Errorf("cannot get stage1 treestoreID for pod %s: %v", p.uuid, err) 93 return 94 } 95 appsTreeStoreIDs, err := p.getAppsTreeStoreIDs() 96 if err != nil { 97 walkErr = fmt.Errorf("cannot get apps treestoreIDs for pod %s: %v", p.uuid, err) 98 return 99 } 100 allTreeStoreIDs := append(appsTreeStoreIDs, stage1TreeStoreID) 101 102 for _, treeStoreID := range allTreeStoreIDs { 103 treeStoreIDs[treeStoreID] = struct{}{} 104 } 105 }); err != nil { 106 return nil, fmt.Errorf("failed to get pod handles: %v", err) 107 } 108 if walkErr != nil { 109 return nil, walkErr 110 } 111 return treeStoreIDs, nil 112 }