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