mirror of https://github.com/docker/docs.git
				
				
				
			Restore ref count
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
		
							parent
							
								
									5f95750ab4
								
							
						
					
					
						commit
						009ee16bef
					
				|  | @ -1,32 +1,69 @@ | |||
| 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
 | ||||
| type RefCounter struct { | ||||
| 	counts map[string]int | ||||
| 	counts map[string]*minfo | ||||
| 	mu     sync.Mutex | ||||
| } | ||||
| 
 | ||||
| // NewRefCounter returns a new 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
 | ||||
| func (c *RefCounter) Increment(id string) int { | ||||
| func (c *RefCounter) Increment(path string) int { | ||||
| 	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() | ||||
| 	return count | ||||
| 	return m.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.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() | ||||
| 	return count | ||||
| 	return m.count | ||||
| } | ||||
|  |  | |||
|  | @ -160,35 +160,35 @@ func (d *Driver) Remove(id string) error { | |||
| // Get mounts a device with given id into the root filesystem
 | ||||
| func (d *Driver) Get(id, mountLabel string) (string, error) { | ||||
| 	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 | ||||
| 	} | ||||
| 
 | ||||
| 	uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) | ||||
| 	if err != nil { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mp) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	// 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) { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mp) | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mp) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	// Mount the device
 | ||||
| 	if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mp) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	rootFs := path.Join(mp, "rootfs") | ||||
| 	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) | ||||
| 		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
 | ||||
| 		// of later problems
 | ||||
| 		if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil { | ||||
| 			d.ctr.Decrement(id) | ||||
| 			d.ctr.Decrement(mp) | ||||
| 			d.DeviceSet.UnmountDevice(id, mp) | ||||
| 			return "", err | ||||
| 		} | ||||
|  | @ -209,10 +209,10 @@ func (d *Driver) Get(id, mountLabel string) (string, error) { | |||
| 
 | ||||
| // Put unmounts a device and removes it.
 | ||||
| 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 | ||||
| 	} | ||||
| 	mp := path.Join(d.home, "mnt", id) | ||||
| 	err := d.DeviceSet.UnmountDevice(id, mp) | ||||
| 	if err != nil { | ||||
| 		logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err) | ||||
|  |  | |||
|  | @ -340,6 +340,10 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) { | |||
| 	if _, err := os.Stat(dir); err != nil { | ||||
| 		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
 | ||||
| 	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") | ||||
| 	upperDir := path.Join(dir, "upper") | ||||
| 	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) | ||||
| 
 | ||||
| 	// 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 { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mergedDir) | ||||
| 		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
 | ||||
| 	// user namespace requires this to move a directory from lower to upper.
 | ||||
| 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) | ||||
| 	if err != nil { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mergedDir) | ||||
| 		syscall.Unmount(mergedDir, 0) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mergedDir) | ||||
| 		syscall.Unmount(mergedDir, 0) | ||||
| 		return "", err | ||||
| 	} | ||||
|  | @ -408,13 +396,14 @@ func (d *Driver) mounted(dir string) (bool, error) { | |||
| 
 | ||||
| // Put unmounts the mount path created for the give id.
 | ||||
| func (d *Driver) Put(id string) error { | ||||
| 	if count := d.ctr.Decrement(id); count > 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	d.pathCacheLock.Lock() | ||||
| 	mountpoint, exists := d.pathCache[id] | ||||
| 	d.pathCacheLock.Unlock() | ||||
| 
 | ||||
| 	if count := d.ctr.Decrement(mountpoint); count > 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if !exists { | ||||
| 		logrus.Debugf("Put on a non-mounted device %s", id) | ||||
| 		// but it might be still here
 | ||||
|  |  | |||
|  | @ -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.
 | ||||
| func (d *Driver) Get(id, mountLabel string) (string, error) { | ||||
| 	mountpoint := d.mountPath(id) | ||||
| 	if count := d.ctr.Increment(id); count > 1 { | ||||
| 	if count := d.ctr.Increment(mountpoint); count > 1 { | ||||
| 		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) | ||||
| 	if err != nil { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mountpoint) | ||||
| 		return "", err | ||||
| 	} | ||||
| 	// Create the target directories if they don't exist
 | ||||
| 	if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil { | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mountpoint) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	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) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -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):
 | ||||
| 	if err := os.Chown(mountpoint, rootUID, rootGID); err != nil { | ||||
| 		mount.Unmount(mountpoint) | ||||
| 		d.ctr.Decrement(id) | ||||
| 		d.ctr.Decrement(mountpoint) | ||||
| 		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.
 | ||||
| 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 | ||||
| 	} | ||||
| 	mountpoint := d.mountPath(id) | ||||
| 	mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint) | ||||
| 	if err != nil || !mounted { | ||||
| 		return err | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| // +build experimental
 | ||||
| 
 | ||||
| package libcontainerd | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -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) | ||||
| } | ||||
		Loading…
	
		Reference in New Issue