devmapper: Allow specifying filesystem for thin devices

This adds the following --storage-opts for the daemon:
dm.fs: The filesystem to use for the base image
dm.mkfsarg: Add an argument to the mkfs command for the base image
dm.mountopt: Add a mount option for devicemapper mount

Currently supported filesystems are xfs and ext4.

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
This commit is contained in:
Alexander Larsson 2014-03-18 14:23:43 +01:00
parent 10083f4140
commit 807bc2cd04
3 changed files with 78 additions and 7 deletions

View File

@ -71,3 +71,27 @@ Here is the list of supported options:
``docker -d --storage-opt dm.loopmetadatasize=4G`` ``docker -d --storage-opt dm.loopmetadatasize=4G``
* `dm.fs`
Specifies the filesystem type to use for the base device. The supported
options are "ext4" and "xfs". The default is "ext4"
Example use:
``docker -d --storage-opt dm.fs=xfs``
* `dm.mkfsarg`
Specifies extra mkfs arguments to be used when creating the base device.
Example use:
``docker -d --storage-opt "dm.mkfsarg=-O ^has_journal"``
* `dm.mountopt`
Specifies extra mount options used when mounting the thin devices.
Example use:
``docker -d --storage-opt dm.mountopt=nodiscard``

View File

@ -72,6 +72,9 @@ type DeviceSet struct {
dataLoopbackSize int64 dataLoopbackSize int64
metaDataLoopbackSize int64 metaDataLoopbackSize int64
baseFsSize uint64 baseFsSize uint64
filesystem string
mountOptions string
mkfsArgs []string
} }
type DiskUsage struct { type DiskUsage struct {
@ -281,14 +284,30 @@ func (devices *DeviceSet) activateDeviceIfNeeded(info *DevInfo) error {
func (devices *DeviceSet) createFilesystem(info *DevInfo) error { func (devices *DeviceSet) createFilesystem(info *DevInfo) error {
devname := info.DevName() devname := info.DevName()
err := exec.Command("mkfs.ext4", "-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0", devname).Run() args := []string{}
if err != nil { for _, arg := range devices.mkfsArgs {
err = exec.Command("mkfs.ext4", "-E", "nodiscard,lazy_itable_init=0", devname).Run() args = append(args, arg)
}
args = append(args, devname)
var err error
switch devices.filesystem {
case "xfs":
err = exec.Command("mkfs.xfs", args...).Run()
case "ext4":
err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0"}, args...)...).Run()
if err != nil {
err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0"}, args...)...).Run()
}
default:
err = fmt.Errorf("Unsupported filesystem type %s", devices.filesystem)
} }
if err != nil { if err != nil {
utils.Debugf("\n--->Err: %s\n", err) utils.Debugf("\n--->Err: %s\n", err)
return err return err
} }
return nil return nil
} }
@ -926,11 +945,19 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
return err return err
} }
mountOptions := label.FormatMountLabel("discard", mountLabel) options := ""
err = syscall.Mount(info.DevName(), path, fstype, flags, mountOptions)
if fstype == "xfs" {
// XFS needs nouuid or it can't mount filesystems with the same fs
options = joinMountOptions(options, "nouuid")
}
options = joinMountOptions(options, devices.mountOptions)
options = joinMountOptions(options, label.FormatMountLabel("", mountLabel))
err = syscall.Mount(info.DevName(), path, fstype, flags, joinMountOptions("discard", options))
if err != nil && err == syscall.EINVAL { if err != nil && err == syscall.EINVAL {
mountOptions = label.FormatMountLabel("", mountLabel) err = syscall.Mount(info.DevName(), path, fstype, flags, options)
err = syscall.Mount(info.DevName(), path, fstype, flags, mountOptions)
} }
if err != nil { if err != nil {
return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err) return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err)
@ -1112,6 +1139,7 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
dataLoopbackSize: DefaultDataLoopbackSize, dataLoopbackSize: DefaultDataLoopbackSize,
metaDataLoopbackSize: DefaultMetaDataLoopbackSize, metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
baseFsSize: DefaultBaseFsSize, baseFsSize: DefaultBaseFsSize,
filesystem: "ext4",
} }
for _, option := range options { for _, option := range options {
@ -1139,6 +1167,15 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
return nil, err return nil, err
} }
devices.metaDataLoopbackSize = size devices.metaDataLoopbackSize = size
case "dm.fs":
if val != "ext4" && val != "xfs" {
return nil, fmt.Errorf("Unsupported filesystem %s\n", val)
}
devices.filesystem = val
case "dm.mkfsarg":
devices.mkfsArgs = append(devices.mkfsArgs, val)
case "dm.mountopt":
devices.mountOptions = joinMountOptions(devices.mountOptions, val)
default: default:
return nil, fmt.Errorf("Unknown option %s\n", key) return nil, fmt.Errorf("Unknown option %s\n", key)
} }

View File

@ -74,3 +74,13 @@ func ProbeFsType(device string) (string, error) {
return "", fmt.Errorf("Unknown filesystem type on %s", device) return "", fmt.Errorf("Unknown filesystem type on %s", device)
} }
func joinMountOptions(a, b string) string {
if a == "" {
return b
}
if b == "" {
return a
}
return a + "," + b
}