|
@@ -181,9 +181,10 @@ func (d *Driver) String() string {
|
|
|
return "zfs"
|
|
|
}
|
|
|
|
|
|
-// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver.
|
|
|
+// Cleanup is called on daemon shutdown. It unmounts the bind mount
|
|
|
+// created by mount.MakePrivate() in Init().
|
|
|
func (d *Driver) Cleanup() error {
|
|
|
- return nil
|
|
|
+ return mount.Unmount(d.options.mountPath)
|
|
|
}
|
|
|
|
|
|
// Status returns information about the ZFS filesystem. It returns a two dimensional array of information
|
|
@@ -357,11 +358,24 @@ 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) (containerfs.ContainerFS, error) {
|
|
|
+func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr error) {
|
|
|
mountpoint := d.mountPath(id)
|
|
|
if count := d.ctr.Increment(mountpoint); count > 1 {
|
|
|
return containerfs.NewLocalContainerFS(mountpoint), nil
|
|
|
}
|
|
|
+ defer func() {
|
|
|
+ if retErr != nil {
|
|
|
+ if c := d.ctr.Decrement(mountpoint); c <= 0 {
|
|
|
+ if mntErr := unix.Unmount(mountpoint, 0); mntErr != nil {
|
|
|
+ logrus.Errorf("Error unmounting %v: %v", mountpoint, mntErr)
|
|
|
+ }
|
|
|
+ if rmErr := unix.Rmdir(mountpoint); rmErr != nil && !os.IsNotExist(rmErr) {
|
|
|
+ logrus.Debugf("Failed to remove %s: %v", id, rmErr)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
|
|
|
filesystem := d.zfsPath(id)
|
|
|
options := label.FormatMountLabel("", mountLabel)
|
|
@@ -369,25 +383,20 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
|
|
|
|
|
|
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
|
|
if err != nil {
|
|
|
- d.ctr.Decrement(mountpoint)
|
|
|
return nil, err
|
|
|
}
|
|
|
// Create the target directories if they don't exist
|
|
|
if err := idtools.MkdirAllAndChown(mountpoint, 0755, idtools.IDPair{rootUID, rootGID}); err != nil {
|
|
|
- d.ctr.Decrement(mountpoint)
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil {
|
|
|
- d.ctr.Decrement(mountpoint)
|
|
|
return nil, fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
|
|
|
}
|
|
|
|
|
|
// this could be our first mount after creation of the filesystem, and the root dir may still have root
|
|
|
// 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(mountpoint)
|
|
|
return nil, fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
|
|
|
}
|
|
|
|
|
@@ -400,16 +409,16 @@ func (d *Driver) Put(id string) error {
|
|
|
if count := d.ctr.Decrement(mountpoint); count > 0 {
|
|
|
return nil
|
|
|
}
|
|
|
- mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint)
|
|
|
- if err != nil || !mounted {
|
|
|
- return err
|
|
|
- }
|
|
|
|
|
|
logrus.Debugf(`[zfs] unmount("%s")`, mountpoint)
|
|
|
|
|
|
- if err := mount.Unmount(mountpoint); err != nil {
|
|
|
- return fmt.Errorf("error unmounting to %s: %v", mountpoint, err)
|
|
|
+ if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil {
|
|
|
+ logrus.Warnf("Failed to unmount %s mount %s: %v", id, mountpoint, err)
|
|
|
}
|
|
|
+ if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) {
|
|
|
+ logrus.Debugf("Failed to remove %s mount point %s: %v", id, mountpoint, err)
|
|
|
+ }
|
|
|
+
|
|
|
return nil
|
|
|
}
|
|
|
|