mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
aufs: 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 free resources related to them. Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
This commit is contained in:
parent
886f650d9b
commit
5fe26ee426
1 changed files with 47 additions and 5 deletions
|
@ -31,6 +31,7 @@ import (
|
|||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -38,7 +39,9 @@ func init() {
|
|||
}
|
||||
|
||||
type Driver struct {
|
||||
root string
|
||||
root string
|
||||
sync.Mutex // Protects concurrent modification to active
|
||||
active map[string]int
|
||||
}
|
||||
|
||||
// New returns a new AUFS driver.
|
||||
|
@ -54,12 +57,17 @@ func Init(root string) (graphdriver.Driver, error) {
|
|||
"layers",
|
||||
}
|
||||
|
||||
a := &Driver{
|
||||
root: root,
|
||||
active: make(map[string]int),
|
||||
}
|
||||
|
||||
// Create the root aufs driver dir and return
|
||||
// if it already exists
|
||||
// If not populate the dir structure
|
||||
if err := os.MkdirAll(root, 0755); err != nil {
|
||||
if os.IsExist(err) {
|
||||
return &Driver{root}, nil
|
||||
return a, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
@ -69,7 +77,7 @@ func Init(root string) (graphdriver.Driver, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Driver{root}, nil
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Return a nil error if the kernel supports aufs
|
||||
|
@ -167,6 +175,14 @@ func (a *Driver) createDirsFor(id string) error {
|
|||
|
||||
// Unmount and remove the dir information
|
||||
func (a *Driver) Remove(id string) error {
|
||||
// Protect the a.active from concurrent access
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
if a.active[id] != 0 {
|
||||
utils.Errorf("Warning: removing active id %s\n", id)
|
||||
}
|
||||
|
||||
// Make sure the dir is umounted first
|
||||
if err := a.unmount(id); err != nil {
|
||||
return err
|
||||
|
@ -210,19 +226,45 @@ func (a *Driver) Get(id string) (string, error) {
|
|||
ids = []string{}
|
||||
}
|
||||
|
||||
// Protect the a.active from concurrent access
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
count := a.active[id]
|
||||
|
||||
// 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)
|
||||
if len(ids) > 0 {
|
||||
out = path.Join(a.rootPath(), "mnt", id)
|
||||
if err := a.mount(id); err != nil {
|
||||
return "", err
|
||||
|
||||
if count == 0 {
|
||||
if err := a.mount(id); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.active[id] = count + 1
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (a *Driver) Put(id string) {
|
||||
// Protect the a.active from concurrent access
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
if count := a.active[id]; count > 1 {
|
||||
a.active[id] = 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)
|
||||
}
|
||||
delete(a.active, id)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an archive of the contents for the id
|
||||
|
|
Loading…
Reference in a new issue