Merge pull request #15868 from crosbymichael/aufs-data

Add aufs data structure for added mount information
This commit is contained in:
Arnaud Porterie 2015-10-08 11:17:20 -07:00
commit b3b9fe8c77
2 changed files with 48 additions and 45 deletions

View File

@ -60,6 +60,11 @@ func init() {
graphdriver.Register("aufs", Init) graphdriver.Register("aufs", Init)
} }
type data struct {
referenceCount int
path string
}
// Driver contains information about the filesystem mounted. // Driver contains information about the filesystem mounted.
// root of the filesystem // root of the filesystem
// sync.Mutex to protect against concurrent modifications // sync.Mutex to protect against concurrent modifications
@ -67,7 +72,7 @@ func init() {
type Driver struct { type Driver struct {
root string root string
sync.Mutex // Protects concurrent modification to active sync.Mutex // Protects concurrent modification to active
active map[string]int active map[string]*data
} }
// Init returns a new AUFS driver. // Init returns a new AUFS driver.
@ -101,7 +106,7 @@ func Init(root string, options []string) (graphdriver.Driver, error) {
a := &Driver{ a := &Driver{
root: root, root: root,
active: make(map[string]int), active: make(map[string]*data),
} }
// Create the root aufs driver dir // Create the root aufs driver dir
@ -206,6 +211,7 @@ func (a *Driver) Create(id, parent string) error {
} }
} }
} }
a.active[id] = &data{}
return nil return nil
} }
@ -229,13 +235,15 @@ func (a *Driver) Remove(id string) error {
a.Lock() a.Lock()
defer a.Unlock() defer a.Unlock()
if a.active[id] != 0 { m := a.active[id]
logrus.Errorf("Removing active id %s", id) if m != nil {
} if m.referenceCount > 0 {
return nil
// Make sure the dir is umounted first }
if err := a.unmount(id); err != nil { // Make sure the dir is umounted first
return err if err := a.unmount(m); err != nil {
return err
}
} }
tmpDirs := []string{ tmpDirs := []string{
"mnt", "mnt",
@ -246,7 +254,6 @@ func (a *Driver) Remove(id string) error {
// way (so that docker doesn't find it anymore) before doing removal of // way (so that docker doesn't find it anymore) before doing removal of
// the whole tree. // the whole tree.
for _, p := range tmpDirs { for _, p := range tmpDirs {
realPath := path.Join(a.rootPath(), p, id) realPath := path.Join(a.rootPath(), p, id)
tmpPath := path.Join(a.rootPath(), p, fmt.Sprintf("%s-removing", id)) tmpPath := path.Join(a.rootPath(), p, fmt.Sprintf("%s-removing", id))
if err := os.Rename(realPath, tmpPath); err != nil && !os.IsNotExist(err) { if err := os.Rename(realPath, tmpPath); err != nil && !os.IsNotExist(err) {
@ -254,7 +261,6 @@ func (a *Driver) Remove(id string) error {
} }
defer os.RemoveAll(tmpPath) defer os.RemoveAll(tmpPath)
} }
// Remove the layers file for the id // Remove the layers file for the id
if err := os.Remove(path.Join(a.rootPath(), "layers", id)); err != nil && !os.IsNotExist(err) { if err := os.Remove(path.Join(a.rootPath(), "layers", id)); err != nil && !os.IsNotExist(err) {
return err return err
@ -277,24 +283,25 @@ func (a *Driver) Get(id, mountLabel string) (string, error) {
a.Lock() a.Lock()
defer a.Unlock() defer a.Unlock()
count := a.active[id] m := a.active[id]
if m == nil {
m = &data{}
a.active[id] = m
}
// If a dir does not have a parent ( no layers )do not try to mount // If a dir does not have a parent ( no layers )do not try to mount
// just return the diff path to the data // just return the diff path to the data
out := path.Join(a.rootPath(), "diff", id) m.path = path.Join(a.rootPath(), "diff", id)
if len(ids) > 0 { if len(ids) > 0 {
out = path.Join(a.rootPath(), "mnt", id) m.path = path.Join(a.rootPath(), "mnt", id)
if m.referenceCount == 0 {
if count == 0 { if err := a.mount(id, m, mountLabel); err != nil {
if err := a.mount(id, mountLabel); err != nil {
return "", err return "", err
} }
} }
} }
m.referenceCount++
a.active[id] = count + 1 return m.path, nil
return out, nil
} }
// Put unmounts and updates list of active mounts. // Put unmounts and updates list of active mounts.
@ -303,13 +310,17 @@ func (a *Driver) Put(id string) error {
a.Lock() a.Lock()
defer a.Unlock() defer a.Unlock()
if count := a.active[id]; count > 1 { m := a.active[id]
a.active[id] = count - 1 if m == nil {
return nil
}
if count := m.referenceCount; count > 1 {
m.referenceCount = count - 1
} else { } else {
ids, _ := getParentIds(a.rootPath(), id) ids, _ := getParentIds(a.rootPath(), id)
// We only mounted if there are any parents // We only mounted if there are any parents
if ids != nil && len(ids) > 0 { if ids != nil && len(ids) > 0 {
a.unmount(id) a.unmount(m)
} }
delete(a.active, id) delete(a.active, id)
} }
@ -376,14 +387,14 @@ func (a *Driver) getParentLayerPaths(id string) ([]string, error) {
return layers, nil return layers, nil
} }
func (a *Driver) mount(id, mountLabel string) error { func (a *Driver) mount(id string, m *data, mountLabel string) error {
// If the id is mounted or we get an error return // If the id is mounted or we get an error return
if mounted, err := a.mounted(id); err != nil || mounted { if mounted, err := a.mounted(m); err != nil || mounted {
return err return err
} }
var ( var (
target = path.Join(a.rootPath(), "mnt", id) target = m.path
rw = path.Join(a.rootPath(), "diff", id) rw = path.Join(a.rootPath(), "diff", id)
) )
@ -398,32 +409,24 @@ func (a *Driver) mount(id, mountLabel string) error {
return nil return nil
} }
func (a *Driver) unmount(id string) error { func (a *Driver) unmount(m *data) error {
if mounted, err := a.mounted(id); err != nil || !mounted { if mounted, err := a.mounted(m); err != nil || !mounted {
return err return err
} }
target := path.Join(a.rootPath(), "mnt", id) return Unmount(m.path)
return Unmount(target)
} }
func (a *Driver) mounted(id string) (bool, error) { func (a *Driver) mounted(m *data) (bool, error) {
target := path.Join(a.rootPath(), "mnt", id) return mountpk.Mounted(m.path)
return mountpk.Mounted(target)
} }
// Cleanup aufs and unmount all mountpoints // Cleanup aufs and unmount all mountpoints
func (a *Driver) Cleanup() error { func (a *Driver) Cleanup() error {
ids, err := loadIds(path.Join(a.rootPath(), "layers")) for id, m := range a.active {
if err != nil { if err := a.unmount(m); err != nil {
return err
}
for _, id := range ids {
if err := a.unmount(id); err != nil {
logrus.Errorf("Unmounting %s: %s", stringid.TruncateID(id), err) logrus.Errorf("Unmounting %s: %s", stringid.TruncateID(id), err)
} }
} }
return mountpk.Unmount(a.root) return mountpk.Unmount(a.root)
} }

View File

@ -198,7 +198,7 @@ func TestMountedFalseResponse(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
response, err := d.mounted("1") response, err := d.mounted(d.active["1"])
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -225,7 +225,7 @@ func TestMountedTrueReponse(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
response, err := d.mounted("2") response, err := d.mounted(d.active["2"])
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -291,7 +291,7 @@ func TestRemoveMountedDir(t *testing.T) {
t.Fatal("mntPath should not be empty string") t.Fatal("mntPath should not be empty string")
} }
mounted, err := d.mounted("2") mounted, err := d.mounted(d.active["2"])
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }