Browse Source

Restore ref count

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Michael Crosby 9 năm trước cách đây
mục cha
commit
009ee16bef

+ 48 - 11
daemon/graphdriver/counter.go

@@ -1,32 +1,69 @@
 package graphdriver
 package graphdriver
 
 
-import "sync"
+import (
+	"sync"
+
+	"github.com/docker/docker/pkg/mount"
+)
+
+type minfo struct {
+	check bool
+	count int
+}
 
 
 // RefCounter is a generic counter for use by graphdriver Get/Put calls
 // RefCounter is a generic counter for use by graphdriver Get/Put calls
 type RefCounter struct {
 type RefCounter struct {
-	counts map[string]int
+	counts map[string]*minfo
 	mu     sync.Mutex
 	mu     sync.Mutex
 }
 }
 
 
 // NewRefCounter returns a new RefCounter
 // NewRefCounter returns a new RefCounter
 func NewRefCounter() *RefCounter {
 func NewRefCounter() *RefCounter {
-	return &RefCounter{counts: make(map[string]int)}
+	return &RefCounter{counts: make(map[string]*minfo)}
 }
 }
 
 
 // Increment increaes the ref count for the given id and returns the current count
 // Increment increaes the ref count for the given id and returns the current count
-func (c *RefCounter) Increment(id string) int {
+func (c *RefCounter) Increment(path string) int {
 	c.mu.Lock()
 	c.mu.Lock()
-	c.counts[id]++
-	count := c.counts[id]
+	m := c.counts[path]
+	if m == nil {
+		m = &minfo{check: true}
+		c.counts[path] = m
+	}
+	// if we are checking this path for the first time check to make sure
+	// if it was already mounted on the system and make sure we have a correct ref
+	// count if it is mounted as it is in use.
+	if !m.check {
+		m.check = true
+		mntd, _ := mount.Mounted(path)
+		if mntd {
+			m.count++
+		}
+	}
+	m.count++
 	c.mu.Unlock()
 	c.mu.Unlock()
-	return count
+	return m.count
 }
 }
 
 
 // Decrement decreases the ref count for the given id and returns the current count
 // Decrement decreases the ref count for the given id and returns the current count
-func (c *RefCounter) Decrement(id string) int {
+func (c *RefCounter) Decrement(path string) int {
 	c.mu.Lock()
 	c.mu.Lock()
-	c.counts[id]--
-	count := c.counts[id]
+	m := c.counts[path]
+	if m == nil {
+		m = &minfo{check: true}
+		c.counts[path] = m
+	}
+	// if we are checking this path for the first time check to make sure
+	// if it was already mounted on the system and make sure we have a correct ref
+	// count if it is mounted as it is in use.
+	if !m.check {
+		m.check = true
+		mntd, _ := mount.Mounted(path)
+		if mntd {
+			m.count++
+		}
+	}
+	m.count--
 	c.mu.Unlock()
 	c.mu.Unlock()
-	return count
+	return m.count
 }
 }

+ 9 - 9
daemon/graphdriver/devmapper/driver.go

@@ -160,35 +160,35 @@ func (d *Driver) Remove(id string) error {
 // Get mounts a device with given id into the root filesystem
 // Get mounts a device with given id into the root filesystem
 func (d *Driver) Get(id, mountLabel string) (string, error) {
 func (d *Driver) Get(id, mountLabel string) (string, error) {
 	mp := path.Join(d.home, "mnt", id)
 	mp := path.Join(d.home, "mnt", id)
-	if count := d.ctr.Increment(id); count > 1 {
+	if count := d.ctr.Increment(mp); count > 1 {
 		return mp, nil
 		return mp, nil
 	}
 	}
 
 
 	uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	if err != nil {
 	if err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mp)
 		return "", err
 		return "", err
 	}
 	}
 
 
 	// Create the target directories if they don't exist
 	// Create the target directories if they don't exist
 	if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil && !os.IsExist(err) {
 	if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil && !os.IsExist(err) {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mp)
 		return "", err
 		return "", err
 	}
 	}
 	if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) {
 	if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mp)
 		return "", err
 		return "", err
 	}
 	}
 
 
 	// Mount the device
 	// Mount the device
 	if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil {
 	if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mp)
 		return "", err
 		return "", err
 	}
 	}
 
 
 	rootFs := path.Join(mp, "rootfs")
 	rootFs := path.Join(mp, "rootfs")
 	if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
 	if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mp)
 		d.DeviceSet.UnmountDevice(id, mp)
 		d.DeviceSet.UnmountDevice(id, mp)
 		return "", err
 		return "", err
 	}
 	}
@@ -198,7 +198,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
 		// Create an "id" file with the container/image id in it to help reconstruct this in case
 		// Create an "id" file with the container/image id in it to help reconstruct this in case
 		// of later problems
 		// of later problems
 		if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil {
 		if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil {
-			d.ctr.Decrement(id)
+			d.ctr.Decrement(mp)
 			d.DeviceSet.UnmountDevice(id, mp)
 			d.DeviceSet.UnmountDevice(id, mp)
 			return "", err
 			return "", err
 		}
 		}
@@ -209,10 +209,10 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
 
 
 // Put unmounts a device and removes it.
 // Put unmounts a device and removes it.
 func (d *Driver) Put(id string) error {
 func (d *Driver) Put(id string) error {
-	if count := d.ctr.Decrement(id); count > 0 {
+	mp := path.Join(d.home, "mnt", id)
+	if count := d.ctr.Decrement(mp); count > 0 {
 		return nil
 		return nil
 	}
 	}
-	mp := path.Join(d.home, "mnt", id)
 	err := d.DeviceSet.UnmountDevice(id, mp)
 	err := d.DeviceSet.UnmountDevice(id, mp)
 	if err != nil {
 	if err != nil {
 		logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err)
 		logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err)

+ 11 - 22
daemon/graphdriver/overlay/overlay.go

@@ -340,6 +340,10 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) {
 	if _, err := os.Stat(dir); err != nil {
 	if _, err := os.Stat(dir); err != nil {
 		return "", err
 		return "", err
 	}
 	}
+	mergedDir := path.Join(dir, "merged")
+	if count := d.ctr.Increment(mergedDir); count > 1 {
+		return mergedDir, nil
+	}
 
 
 	// If id has a root, just return it
 	// If id has a root, just return it
 	rootDir := path.Join(dir, "root")
 	rootDir := path.Join(dir, "root")
@@ -357,40 +361,24 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) {
 	lowerDir := path.Join(d.dir(string(lowerID)), "root")
 	lowerDir := path.Join(d.dir(string(lowerID)), "root")
 	upperDir := path.Join(dir, "upper")
 	upperDir := path.Join(dir, "upper")
 	workDir := path.Join(dir, "work")
 	workDir := path.Join(dir, "work")
-	mergedDir := path.Join(dir, "merged")
-
-	if count := d.ctr.Increment(id); count > 1 {
-		return mergedDir, nil
-	}
 
 
 	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir)
 	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir)
 
 
-	// if it's mounted already, just return
-	mounted, err := d.mounted(mergedDir)
-	if err != nil {
-		d.ctr.Decrement(id)
-		return "", err
-	}
-	if mounted {
-		d.ctr.Decrement(id)
-		return mergedDir, nil
-	}
-
 	if err := syscall.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil {
 	if err := syscall.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mergedDir)
 		return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
 		return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
 	}
 	}
 	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
 	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
 	// user namespace requires this to move a directory from lower to upper.
 	// user namespace requires this to move a directory from lower to upper.
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	if err != nil {
 	if err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mergedDir)
 		syscall.Unmount(mergedDir, 0)
 		syscall.Unmount(mergedDir, 0)
 		return "", err
 		return "", err
 	}
 	}
 
 
 	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
 	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mergedDir)
 		syscall.Unmount(mergedDir, 0)
 		syscall.Unmount(mergedDir, 0)
 		return "", err
 		return "", err
 	}
 	}
@@ -408,13 +396,14 @@ func (d *Driver) mounted(dir string) (bool, error) {
 
 
 // Put unmounts the mount path created for the give id.
 // Put unmounts the mount path created for the give id.
 func (d *Driver) Put(id string) error {
 func (d *Driver) Put(id string) error {
-	if count := d.ctr.Decrement(id); count > 0 {
-		return nil
-	}
 	d.pathCacheLock.Lock()
 	d.pathCacheLock.Lock()
 	mountpoint, exists := d.pathCache[id]
 	mountpoint, exists := d.pathCache[id]
 	d.pathCacheLock.Unlock()
 	d.pathCacheLock.Unlock()
 
 
+	if count := d.ctr.Decrement(mountpoint); count > 0 {
+		return nil
+	}
+
 	if !exists {
 	if !exists {
 		logrus.Debugf("Put on a non-mounted device %s", id)
 		logrus.Debugf("Put on a non-mounted device %s", id)
 		// but it might be still here
 		// but it might be still here

+ 7 - 7
daemon/graphdriver/zfs/zfs.go

@@ -307,7 +307,7 @@ func (d *Driver) Remove(id string) error {
 // Get returns the mountpoint for the given id after creating the target directories if necessary.
 // Get returns the mountpoint for the given id after creating the target directories if necessary.
 func (d *Driver) Get(id, mountLabel string) (string, error) {
 func (d *Driver) Get(id, mountLabel string) (string, error) {
 	mountpoint := d.mountPath(id)
 	mountpoint := d.mountPath(id)
-	if count := d.ctr.Increment(id); count > 1 {
+	if count := d.ctr.Increment(mountpoint); count > 1 {
 		return mountpoint, nil
 		return mountpoint, nil
 	}
 	}
 
 
@@ -317,17 +317,17 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
 
 
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	if err != nil {
 	if err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mountpoint)
 		return "", err
 		return "", err
 	}
 	}
 	// Create the target directories if they don't exist
 	// Create the target directories if they don't exist
 	if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil {
 	if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mountpoint)
 		return "", err
 		return "", err
 	}
 	}
 
 
 	if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil {
 	if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil {
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mountpoint)
 		return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
 		return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
 	}
 	}
 
 
@@ -335,7 +335,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
 	// permissions instead of the remapped root uid:gid (if user namespaces are enabled):
 	// permissions instead of the remapped root uid:gid (if user namespaces are enabled):
 	if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
 	if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
 		mount.Unmount(mountpoint)
 		mount.Unmount(mountpoint)
-		d.ctr.Decrement(id)
+		d.ctr.Decrement(mountpoint)
 		return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
 		return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
 	}
 	}
 
 
@@ -344,10 +344,10 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
 
 
 // Put removes the existing mountpoint for the given id if it exists.
 // Put removes the existing mountpoint for the given id if it exists.
 func (d *Driver) Put(id string) error {
 func (d *Driver) Put(id string) error {
-	if count := d.ctr.Decrement(id); count > 0 {
+	mountpoint := d.mountPath(id)
+	if count := d.ctr.Decrement(mountpoint); count > 0 {
 		return nil
 		return nil
 	}
 	}
-	mountpoint := d.mountPath(id)
 	mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint)
 	mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint)
 	if err != nil || !mounted {
 	if err != nil || !mounted {
 		return err
 		return err

+ 0 - 2
libcontainerd/client_liverestore_linux.go

@@ -1,5 +1,3 @@
-// +build experimental
-
 package libcontainerd
 package libcontainerd
 
 
 import (
 import (

+ 0 - 41
libcontainerd/client_shutdownrestore_linux.go

@@ -1,41 +0,0 @@
-// +build !experimental
-
-package libcontainerd
-
-import (
-	"syscall"
-	"time"
-
-	"github.com/Sirupsen/logrus"
-)
-
-func (clnt *client) Restore(containerID string, options ...CreateOption) error {
-	w := clnt.getOrCreateExitNotifier(containerID)
-	defer w.close()
-	cont, err := clnt.getContainerdContainer(containerID)
-	if err == nil && cont.Status != "stopped" {
-		clnt.lock(cont.Id)
-		container := clnt.newContainer(cont.BundlePath)
-		container.systemPid = systemPid(cont)
-		clnt.appendContainer(container)
-		clnt.unlock(cont.Id)
-
-		if err := clnt.Signal(containerID, int(syscall.SIGTERM)); err != nil {
-			logrus.Errorf("error sending sigterm to %v: %v", containerID, err)
-		}
-		select {
-		case <-time.After(10 * time.Second):
-			if err := clnt.Signal(containerID, int(syscall.SIGKILL)); err != nil {
-				logrus.Errorf("error sending sigkill to %v: %v", containerID, err)
-			}
-			select {
-			case <-time.After(2 * time.Second):
-			case <-w.wait():
-				return nil
-			}
-		case <-w.wait():
-			return nil
-		}
-	}
-	return clnt.setExited(containerID)
-}