Skip to content

Commit

Permalink
containers-storage: add new option .fuse_program
Browse files Browse the repository at this point in the history
When specified the mount of the overlay file system is delegated to
the specified command instead of mounting it directly.

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Jun 29, 2018
1 parent 51f1f85 commit fc4b862
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
4 changes: 4 additions & 0 deletions docs/containers-storage.conf.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ Tells driver to wipe device (directlvm_device) even if device already has a file

Specifies the filesystem type to use for the base device. (default: xfs)

**fuse_program**=""

Specifies the path to a custom FUSE program to use instead for mounting the file system.

**log_level**=""

Sets the log level of devicemapper.
Expand Down
38 changes: 30 additions & 8 deletions drivers/overlay/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type overlayOptions struct {
overrideKernelCheck bool
imageStores []string
quota quota.Quota
fuseProgram string
}

// Driver contains information about the home directory and the list of active mounts that are created using this driver.
Expand Down Expand Up @@ -147,11 +148,16 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
return nil, err
}

supportsDType, err := supportsOverlay(home, fsMagic, rootUID, rootGID)
if err != nil {
os.Remove(filepath.Join(home, linkDir))
os.Remove(home)
return nil, errors.Wrap(err, "kernel does not support overlay fs")
var supportsDType bool
if opts.fuseProgram != "" {
supportsDType = true
} else {
supportsDType, err = supportsOverlay(home, fsMagic, rootUID, rootGID)
if err != nil {
os.Remove(filepath.Join(home, linkDir))
os.Remove(home)
return nil, errors.Wrap(err, "kernel does not support overlay fs")
}
}

if err := mount.MakePrivate(home); err != nil {
Expand Down Expand Up @@ -227,6 +233,13 @@ func parseOptions(options []string) (*overlayOptions, error) {
}
o.imageStores = append(o.imageStores, store)
}
case ".fuse_program", "overlay.fuse_program", "overlay2.fuse_program":
logrus.Debugf("overlay: fuse_program=%s", val)
_, err := os.Stat(val)
if err != nil {
return nil, fmt.Errorf("overlay: can't stat FUSE program %s: %v", val, err)
}
o.fuseProgram = val
default:
return nil, fmt.Errorf("overlay: Unknown option %s", key)
}
Expand All @@ -236,6 +249,7 @@ func parseOptions(options []string) (*overlayOptions, error) {

func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGID int) (supportsDType bool, err error) {
// We can try to modprobe overlay first

exec.Command("modprobe", "overlay").Run()

layerDir, err := ioutil.TempDir(home, "compat")
Expand Down Expand Up @@ -663,16 +677,24 @@ func (d *Driver) Get(id, mountLabel string) (_ string, retErr error) {
// the page size. The mount syscall fails if the mount data cannot
// fit within a page and relative links make the mount data much
// smaller at the expense of requiring a fork exec to chroot.
if len(mountData) > pageSize {
if len(mountData) > pageSize || d.options.fuseProgram != "" {
//FIXME: We need to figure out to get this to work with additional stores
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(relLowers, ":"), path.Join(id, "diff"), path.Join(id, "work"))
mountData = label.FormatMountLabel(opts, mountLabel)
if len(mountData) > pageSize {
return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
}

mount = func(source string, target string, mType string, flags uintptr, label string) error {
return mountFrom(d.home, source, target, mType, flags, label)
if d.options.fuseProgram != "" {
mount = func(source string, target string, mType string, flags uintptr, label string) error {
cmdRootless := exec.Command(d.options.fuseProgram, "-o", label, target)
cmdRootless.Dir = d.home
return cmdRootless.Run()
}
} else {
mount = func(source string, target string, mType string, flags uintptr, label string) error {
return mountFrom(d.home, source, target, mType, flags, label)
}
}
mountTarget = path.Join(id, "merged")
}
Expand Down

0 comments on commit fc4b862

Please sign in to comment.