devmapper: Add options for specifying block devices
This adds dm.datadev and dm.metadatadev options that you can use with --storage-opt to set to specific devices to use for the thin provisioning pool. Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
This commit is contained in:
parent
807bc2cd04
commit
a226168a8b
2 changed files with 97 additions and 29 deletions
|
@ -95,3 +95,33 @@ Here is the list of supported options:
|
|||
Example use:
|
||||
|
||||
``docker -d --storage-opt dm.mountopt=nodiscard``
|
||||
|
||||
* `dm.datadev`
|
||||
|
||||
Specifies a custom blockdevice to use for data for the thin pool.
|
||||
|
||||
If using a block device for device mapper storage, ideally both
|
||||
datadev and metadatadev should be specified to completely avoid
|
||||
using the loopback device.
|
||||
|
||||
Example use:
|
||||
|
||||
``docker -d --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1``
|
||||
|
||||
* `dm.metadatadev`
|
||||
|
||||
Specifies a custom blockdevice to use for metadata for the thin
|
||||
pool.
|
||||
|
||||
For best performance the metadata should be on a different spindle
|
||||
than the data, or even better on an SSD.
|
||||
|
||||
If setting up a new metadata pool it is required to be valid. This
|
||||
can be achieved by zeroing the first 4k to indicate empty
|
||||
metadata, like this:
|
||||
|
||||
``dd if=/dev/zero of=$metadata_dev bs=4096 count=1```
|
||||
|
||||
Example use:
|
||||
|
||||
``docker -d --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1``
|
||||
|
|
|
@ -75,6 +75,8 @@ type DeviceSet struct {
|
|||
filesystem string
|
||||
mountOptions string
|
||||
mkfsArgs []string
|
||||
dataDevice string
|
||||
metadataDevice string
|
||||
}
|
||||
|
||||
type DiskUsage struct {
|
||||
|
@ -581,42 +583,74 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
|||
if info.Exists == 0 {
|
||||
utils.Debugf("Pool doesn't exist. Creating it.")
|
||||
|
||||
var (
|
||||
dataFile *os.File
|
||||
metadataFile *os.File
|
||||
)
|
||||
|
||||
if devices.dataDevice == "" {
|
||||
// Make sure the sparse images exist in <root>/devicemapper/data
|
||||
|
||||
hasData := devices.hasImage("data")
|
||||
hasMetadata := devices.hasImage("metadata")
|
||||
|
||||
if !doInit && !hasData {
|
||||
return errors.New("Loopback data file not found")
|
||||
}
|
||||
|
||||
if !doInit && !hasMetadata {
|
||||
return errors.New("Loopback metadata file not found")
|
||||
if !hasData {
|
||||
createdLoopback = true
|
||||
}
|
||||
|
||||
createdLoopback = !hasData || !hasMetadata
|
||||
data, err := devices.ensureImage("data", devices.dataLoopbackSize)
|
||||
if err != nil {
|
||||
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
dataFile, err = attachLoopDevice(data)
|
||||
if err != nil {
|
||||
utils.Debugf("\n--->Err: %s\n", err)
|
||||
return err
|
||||
}
|
||||
defer dataFile.Close()
|
||||
} else {
|
||||
dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if devices.metadataDevice == "" {
|
||||
// Make sure the sparse images exist in <root>/devicemapper/metadata
|
||||
|
||||
hasMetadata := devices.hasImage("metadata")
|
||||
|
||||
if !doInit && !hasMetadata {
|
||||
return errors.New("Loopback metadata file not found")
|
||||
}
|
||||
|
||||
if !hasMetadata {
|
||||
createdLoopback = true
|
||||
}
|
||||
|
||||
metadata, err := devices.ensureImage("metadata", devices.metaDataLoopbackSize)
|
||||
if err != nil {
|
||||
utils.Debugf("Error device ensureImage (metadata): %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
dataFile, err := attachLoopDevice(data)
|
||||
if err != nil {
|
||||
utils.Debugf("\n--->Err: %s\n", err)
|
||||
return err
|
||||
}
|
||||
defer dataFile.Close()
|
||||
|
||||
metadataFile, err := attachLoopDevice(metadata)
|
||||
metadataFile, err = attachLoopDevice(metadata)
|
||||
if err != nil {
|
||||
utils.Debugf("\n--->Err: %s\n", err)
|
||||
return err
|
||||
}
|
||||
defer metadataFile.Close()
|
||||
} else {
|
||||
metadataFile, err = os.OpenFile(devices.metadataDevice, os.O_RDWR, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := createPool(devices.getPoolName(), dataFile, metadataFile); err != nil {
|
||||
utils.Debugf("\n--->Err: %s\n", err)
|
||||
|
@ -1176,6 +1210,10 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
|
|||
devices.mkfsArgs = append(devices.mkfsArgs, val)
|
||||
case "dm.mountopt":
|
||||
devices.mountOptions = joinMountOptions(devices.mountOptions, val)
|
||||
case "dm.metadatadev":
|
||||
devices.metadataDevice = val
|
||||
case "dm.datadev":
|
||||
devices.dataDevice = val
|
||||
default:
|
||||
return nil, fmt.Errorf("Unknown option %s\n", key)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue