|
@@ -22,6 +22,12 @@ import (
|
|
|
"github.com/opencontainers/runc/libcontainer/label"
|
|
|
)
|
|
|
|
|
|
+type activeMount struct {
|
|
|
+ count int
|
|
|
+ path string
|
|
|
+ mounted bool
|
|
|
+}
|
|
|
+
|
|
|
type zfsOptions struct {
|
|
|
fsName string
|
|
|
mountPath string
|
|
@@ -103,6 +109,7 @@ func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdri
|
|
|
dataset: rootDataset,
|
|
|
options: options,
|
|
|
filesystemsCache: filesystemsCache,
|
|
|
+ active: make(map[string]*activeMount),
|
|
|
uidMaps: uidMaps,
|
|
|
gidMaps: gidMaps,
|
|
|
}
|
|
@@ -159,6 +166,7 @@ type Driver struct {
|
|
|
options zfsOptions
|
|
|
sync.Mutex // protects filesystem cache against concurrent access
|
|
|
filesystemsCache map[string]bool
|
|
|
+ active map[string]*activeMount
|
|
|
uidMaps []idtools.IDMap
|
|
|
gidMaps []idtools.IDMap
|
|
|
}
|
|
@@ -294,6 +302,17 @@ 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) {
|
|
|
+ d.Lock()
|
|
|
+ defer d.Unlock()
|
|
|
+
|
|
|
+ mnt := d.active[id]
|
|
|
+ if mnt != nil {
|
|
|
+ mnt.count++
|
|
|
+ return mnt.path, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ mnt = &activeMount{count: 1}
|
|
|
+
|
|
|
mountpoint := d.mountPath(id)
|
|
|
filesystem := d.zfsPath(id)
|
|
|
options := label.FormatMountLabel("", mountLabel)
|
|
@@ -316,17 +335,43 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
|
|
if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
|
|
|
return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
|
|
|
}
|
|
|
+ mnt.path = mountpoint
|
|
|
+ mnt.mounted = true
|
|
|
+ d.active[id] = mnt
|
|
|
|
|
|
return mountpoint, nil
|
|
|
}
|
|
|
|
|
|
// Put removes the existing mountpoint for the given id if it exists.
|
|
|
func (d *Driver) Put(id string) error {
|
|
|
- mountpoint := d.mountPath(id)
|
|
|
- logrus.Debugf(`[zfs] unmount("%s")`, mountpoint)
|
|
|
+ d.Lock()
|
|
|
+ defer d.Unlock()
|
|
|
+
|
|
|
+ mnt := d.active[id]
|
|
|
+ if mnt == nil {
|
|
|
+ logrus.Debugf("[zfs] Put on a non-mounted device %s", id)
|
|
|
+ // but it might be still here
|
|
|
+ if d.Exists(id) {
|
|
|
+ err := mount.Unmount(d.mountPath(id))
|
|
|
+ if err != nil {
|
|
|
+ logrus.Debugf("[zfs] Failed to unmount %s zfs fs: %v", id, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
|
|
|
- if err := mount.Unmount(mountpoint); err != nil {
|
|
|
- return fmt.Errorf("error unmounting to %s: %v", mountpoint, err)
|
|
|
+ mnt.count--
|
|
|
+ if mnt.count > 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ defer delete(d.active, id)
|
|
|
+ if mnt.mounted {
|
|
|
+ logrus.Debugf(`[zfs] unmount("%s")`, mnt.path)
|
|
|
+
|
|
|
+ if err := mount.Unmount(mnt.path); err != nil {
|
|
|
+ return fmt.Errorf("error unmounting to %s: %v", mnt.path, err)
|
|
|
+ }
|
|
|
}
|
|
|
return nil
|
|
|
}
|