github.com/adxhyt/docker@v1.4.2-0.20150117221845-467b7c821390/daemon/graphdriver/driver.go (about) 1 package graphdriver 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path" 8 "strings" 9 10 log "github.com/Sirupsen/logrus" 11 "github.com/docker/docker/pkg/archive" 12 ) 13 14 type FsMagic uint32 15 16 const ( 17 FsMagicBtrfs = FsMagic(0x9123683E) 18 FsMagicAufs = FsMagic(0x61756673) 19 FsMagicExtfs = FsMagic(0x0000EF53) 20 FsMagicCramfs = FsMagic(0x28cd3d45) 21 FsMagicRamFs = FsMagic(0x858458f6) 22 FsMagicTmpFs = FsMagic(0x01021994) 23 FsMagicSquashFs = FsMagic(0x73717368) 24 FsMagicNfsFs = FsMagic(0x00006969) 25 FsMagicReiserFs = FsMagic(0x52654973) 26 FsMagicSmbFs = FsMagic(0x0000517B) 27 FsMagicJffs2Fs = FsMagic(0x000072b6) 28 FsMagicUnsupported = FsMagic(0x00000000) 29 ) 30 31 var ( 32 DefaultDriver string 33 // All registred drivers 34 drivers map[string]InitFunc 35 // Slice of drivers that should be used in an order 36 priority = []string{ 37 "aufs", 38 "btrfs", 39 "devicemapper", 40 "vfs", 41 // experimental, has to be enabled manually for now 42 "overlay", 43 } 44 45 ErrNotSupported = errors.New("driver not supported") 46 ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)") 47 ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver") 48 49 FsNames = map[FsMagic]string{ 50 FsMagicAufs: "aufs", 51 FsMagicBtrfs: "btrfs", 52 FsMagicExtfs: "extfs", 53 FsMagicCramfs: "cramfs", 54 FsMagicRamFs: "ramfs", 55 FsMagicTmpFs: "tmpfs", 56 FsMagicSquashFs: "squashfs", 57 FsMagicNfsFs: "nfs", 58 FsMagicReiserFs: "reiserfs", 59 FsMagicSmbFs: "smb", 60 FsMagicJffs2Fs: "jffs2", 61 FsMagicUnsupported: "unsupported", 62 } 63 ) 64 65 type InitFunc func(root string, options []string) (Driver, error) 66 67 // ProtoDriver defines the basic capabilities of a driver. 68 // This interface exists solely to be a minimum set of methods 69 // for client code which choose not to implement the entire Driver 70 // interface and use the NaiveDiffDriver wrapper constructor. 71 // 72 // Use of ProtoDriver directly by client code is not recommended. 73 type ProtoDriver interface { 74 // String returns a string representation of this driver. 75 String() string 76 // Create creates a new, empty, filesystem layer with the 77 // specified id and parent. Parent may be "". 78 Create(id, parent string) error 79 // Remove attempts to remove the filesystem layer with this id. 80 Remove(id string) error 81 // Get returns the mountpoint for the layered filesystem referred 82 // to by this id. You can optionally specify a mountLabel or "". 83 // Returns the absolute path to the mounted layered filesystem. 84 Get(id, mountLabel string) (dir string, err error) 85 // Put releases the system resources for the specified id, 86 // e.g, unmounting layered filesystem. 87 Put(id string) error 88 // Exists returns whether a filesystem layer with the specified 89 // ID exists on this driver. 90 Exists(id string) bool 91 // Status returns a set of key-value pairs which give low 92 // level diagnostic status about this driver. 93 Status() [][2]string 94 // Cleanup performs necessary tasks to release resources 95 // held by the driver, e.g., unmounting all layered filesystems 96 // known to this driver. 97 Cleanup() error 98 } 99 100 // Driver is the interface for layered/snapshot file system drivers. 101 type Driver interface { 102 ProtoDriver 103 // Diff produces an archive of the changes between the specified 104 // layer and its parent layer which may be "". 105 Diff(id, parent string) (archive.Archive, error) 106 // Changes produces a list of changes between the specified layer 107 // and its parent layer. If parent is "", then all changes will be ADD changes. 108 Changes(id, parent string) ([]archive.Change, error) 109 // ApplyDiff extracts the changeset from the given diff into the 110 // layer with the specified id and parent, returning the size of the 111 // new layer in bytes. 112 ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error) 113 // DiffSize calculates the changes between the specified id 114 // and its parent and returns the size in bytes of the changes 115 // relative to its base filesystem directory. 116 DiffSize(id, parent string) (size int64, err error) 117 } 118 119 func init() { 120 drivers = make(map[string]InitFunc) 121 } 122 123 func Register(name string, initFunc InitFunc) error { 124 if _, exists := drivers[name]; exists { 125 return fmt.Errorf("Name already registered %s", name) 126 } 127 drivers[name] = initFunc 128 129 return nil 130 } 131 132 func GetDriver(name, home string, options []string) (Driver, error) { 133 if initFunc, exists := drivers[name]; exists { 134 return initFunc(path.Join(home, name), options) 135 } 136 return nil, ErrNotSupported 137 } 138 139 func New(root string, options []string) (driver Driver, err error) { 140 for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} { 141 if name != "" { 142 return GetDriver(name, root, options) 143 } 144 } 145 146 // Check for priority drivers first 147 for _, name := range priority { 148 driver, err = GetDriver(name, root, options) 149 if err != nil { 150 if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { 151 continue 152 } 153 return nil, err 154 } 155 checkPriorDriver(name, root) 156 return driver, nil 157 } 158 159 // Check all registered drivers if no priority driver is found 160 for name, initFunc := range drivers { 161 if driver, err = initFunc(root, options); err != nil { 162 if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { 163 continue 164 } 165 return nil, err 166 } 167 checkPriorDriver(name, root) 168 return driver, nil 169 } 170 return nil, fmt.Errorf("No supported storage backend found") 171 } 172 173 func checkPriorDriver(name, root string) { 174 priorDrivers := []string{} 175 for prior := range drivers { 176 if prior != name && prior != "vfs" { 177 if _, err := os.Stat(path.Join(root, prior)); err == nil { 178 priorDrivers = append(priorDrivers, prior) 179 } 180 } 181 } 182 if len(priorDrivers) > 0 { 183 log.Warnf("graphdriver %s selected. Warning: your graphdriver directory %s already contains data managed by other graphdrivers: %s", name, root, strings.Join(priorDrivers, ",")) 184 } 185 }