浏览代码

devicemapper: Unmount inactive devices

This implements the new Put() operation such that
Get()/Put() maintains a refcount for each ID, mounting
only on first Get() and unmounting on the last Get().

This means we avoid littering the system with lots of mounts
and active devicemapper devices and free resources related
to them.

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)

asdfljk
Alexander Larsson 11 年之前
父节点
当前提交
886f650d9b
共有 1 个文件被更改,包括 38 次插入3 次删除
  1. 38 3
      graphdriver/devmapper/driver.go

+ 38 - 3
graphdriver/devmapper/driver.go

@@ -5,8 +5,10 @@ package devmapper
 import (
 	"fmt"
 	"github.com/dotcloud/docker/graphdriver"
+	"github.com/dotcloud/docker/utils"
 	"io/ioutil"
 	"path"
+	"sync"
 )
 
 func init() {
@@ -20,7 +22,9 @@ func init() {
 
 type Driver struct {
 	*DeviceSet
-	home string
+	home       string
+	sync.Mutex // Protects concurrent modification to active
+	active     map[string]int
 }
 
 var Init = func(home string) (graphdriver.Driver, error) {
@@ -31,6 +35,7 @@ var Init = func(home string) (graphdriver.Driver, error) {
 	d := &Driver{
 		DeviceSet: deviceSet,
 		home:      home,
+		active:    make(map[string]int),
 	}
 	return d, nil
 }
@@ -82,6 +87,14 @@ func (d *Driver) Create(id, parent string) error {
 }
 
 func (d *Driver) Remove(id string) error {
+	// Protect the d.active from concurrent access
+	d.Lock()
+	defer d.Unlock()
+
+	if d.active[id] != 0 {
+		utils.Errorf("Warning: removing active id %s\n", id)
+	}
+
 	mp := path.Join(d.home, "mnt", id)
 	if err := d.unmount(id, mp); err != nil {
 		return err
@@ -90,14 +103,36 @@ func (d *Driver) Remove(id string) error {
 }
 
 func (d *Driver) Get(id string) (string, error) {
+	// Protect the d.active from concurrent access
+	d.Lock()
+	defer d.Unlock()
+
+	count := d.active[id]
+
 	mp := path.Join(d.home, "mnt", id)
-	if err := d.mount(id, mp); err != nil {
-		return "", err
+	if count == 0 {
+		if err := d.mount(id, mp); err != nil {
+			return "", err
+		}
 	}
+
+	d.active[id] = count + 1
+
 	return path.Join(mp, "rootfs"), nil
 }
 
 func (d *Driver) Put(id string) {
+	// Protect the d.active from concurrent access
+	d.Lock()
+	defer d.Unlock()
+
+	if count := d.active[id]; count > 1 {
+		d.active[id] = count - 1
+	} else {
+		mp := path.Join(d.home, "mnt", id)
+		d.unmount(id, mp)
+		delete(d.active, id)
+	}
 }
 
 func (d *Driver) mount(id, mountPoint string) error {