Преглед изворни кода

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 {