зеркало из https://github.com/microsoft/docker.git
devmapper: Save and restore NextDeviceId in a file
The way thin-pool right now is designed, user space is supposed to keep track of what device ids have already been used. If user space tries to create a new thin/snap device and device id has already been used, thin pool retuns -EEXIST. Upon receiving -EEXIST, current docker implementation simply tries the NextDeviceId++ and keeps on doing this till it finds a free device id. This approach has two issues. - It is little suboptimal. - If device id already exists, current kenrel implementation spits out a messsage on console. [17991.140135] device-mapper: thin: Creation of new snapshot 33 of device 3 failed. Here kenrel is trying to tell user that device id 33 has already been used. And this shows up for every device id docker tries till it reaches a point where device ids are not used. So if there are thousands of container and one is trying to create a new container after fresh docker start, expect thousands of such warnings to flood console. This patch saves the NextDeviceId in a file in /var/lib/docker/devmapper/metadata/deviceset-metadata and reads it back when docker starts. This way we don't retry lots of device ids which have already been used. There might be some device ids which are free but we will get back to them once device numbers wrap around (24bit limit on device ids). This patch should cut down on number of kernel warnings. Notice that I am creating a deviceset metadata file which is a global file for this pool. So down the line if we need to save more data we should be able to do that. Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
Родитель
8e9a18039b
Коммит
8c9e5e5e05
|
@ -62,25 +62,25 @@ type MetaData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceSet struct {
|
type DeviceSet struct {
|
||||||
MetaData
|
MetaData `json:"-"`
|
||||||
sync.Mutex // Protects Devices map and serializes calls into libdevmapper
|
sync.Mutex `json:"-"` // Protects Devices map and serializes calls into libdevmapper
|
||||||
root string
|
root string `json:"-"`
|
||||||
devicePrefix string
|
devicePrefix string `json:"-"`
|
||||||
TransactionId uint64
|
TransactionId uint64 `json:"-"`
|
||||||
NewTransactionId uint64
|
NewTransactionId uint64 `json:"-"`
|
||||||
NextDeviceId int
|
NextDeviceId int `json:"next_device_id"`
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
dataLoopbackSize int64
|
dataLoopbackSize int64 `json:"-"`
|
||||||
metaDataLoopbackSize int64
|
metaDataLoopbackSize int64 `json:"-"`
|
||||||
baseFsSize uint64
|
baseFsSize uint64 `json:"-"`
|
||||||
filesystem string
|
filesystem string `json:"-"`
|
||||||
mountOptions string
|
mountOptions string `json:"-"`
|
||||||
mkfsArgs []string
|
mkfsArgs []string `json:"-"`
|
||||||
dataDevice string
|
dataDevice string `json:"-"`
|
||||||
metadataDevice string
|
metadataDevice string `json:"-"`
|
||||||
doBlkDiscard bool
|
doBlkDiscard bool `json:"-"`
|
||||||
thinpBlockSize uint32
|
thinpBlockSize uint32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiskUsage struct {
|
type DiskUsage struct {
|
||||||
|
@ -138,6 +138,10 @@ func (devices *DeviceSet) metadataFile(info *DevInfo) string {
|
||||||
return path.Join(devices.metadataDir(), file)
|
return path.Join(devices.metadataDir(), file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) deviceSetMetaFile() string {
|
||||||
|
return path.Join(devices.metadataDir(), "deviceset-metadata")
|
||||||
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) oldMetadataFile() string {
|
func (devices *DeviceSet) oldMetadataFile() string {
|
||||||
return path.Join(devices.loopbackDir(), "json")
|
return path.Join(devices.loopbackDir(), "json")
|
||||||
}
|
}
|
||||||
|
@ -545,6 +549,34 @@ func (devices *DeviceSet) ResizePool(size int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) loadDeviceSetMetaData() error {
|
||||||
|
jsonData, err := ioutil.ReadFile(devices.deviceSetMetaFile())
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(jsonData, devices); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) saveDeviceSetMetaData() error {
|
||||||
|
jsonData, err := json.Marshal(devices)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error encoding metadata to json: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = devices.writeMetaFile(jsonData, devices.deviceSetMetaFile())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
logInit(devices)
|
logInit(devices)
|
||||||
|
|
||||||
|
@ -676,6 +708,10 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Right now this loads only NextDeviceId. If there is more metatadata
|
||||||
|
// down the line, we might have to move it earlier.
|
||||||
|
devices.loadDeviceSetMetaData()
|
||||||
|
|
||||||
// Setup the base image
|
// Setup the base image
|
||||||
if doInit {
|
if doInit {
|
||||||
if err := devices.setupBaseImage(); err != nil {
|
if err := devices.setupBaseImage(); err != nil {
|
||||||
|
@ -955,6 +991,8 @@ func (devices *DeviceSet) Shutdown() error {
|
||||||
if err := devices.deactivatePool(); err != nil {
|
if err := devices.deactivatePool(); err != nil {
|
||||||
log.Debugf("Shutdown deactivate pool , error: %s", err)
|
log.Debugf("Shutdown deactivate pool , error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devices.saveDeviceSetMetaData()
|
||||||
devices.Unlock()
|
devices.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
Загрузка…
Ссылка в новой задаче