소스 검색

Add aufs data structure for added mount information

This adds a data struct in the aufs driver for including more
information about active mounts along with their reference count.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Michael Crosby 10 년 전
부모
커밋
20bb065535
2개의 변경된 파일48개의 추가작업 그리고 45개의 파일을 삭제
  1. 45 42
      daemon/graphdriver/aufs/aufs.go
  2. 3 3
      daemon/graphdriver/aufs/aufs_test.go

+ 45 - 42
daemon/graphdriver/aufs/aufs.go

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

+ 3 - 3
daemon/graphdriver/aufs/aufs_test.go

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