From 622c433bcbb5ab83d049da74061fa717d16a92fd Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 3 Dec 2014 13:06:43 -0500 Subject: [PATCH] devmapper: Keep track of used device Ids in a bitmap Currently devicemapper backend does not keep track of used device Ids in the pool. It tries a device Id and if that device Id exists in pool, it tries with a different Id and keeps on doing this in a loop till it succeeds. This worked fine so far but now we are moving to transaction based device creation and deletion. We will keep deviceId information in transaction which will be rolled back if docker crashed before transaction was complete. If we store a deviceId in transaction and later figure out it already existed in pool and docker crashed, then we will rollback and remove that existing device Id from pool (which we should not have). That means, we should know free device Id in pool in advance before we put that device Id in transaction. Hence this patch creates a bitmap (one bit each for a deviceId), and sets the bit if device Id is used otherwise resets it. This patch is just preparing the ground right now. Actual usage will follow in later patches. Signed-off-by: Vivek Goyal Upstream-commit: 4d39e056aac2fadffcb8560101f3c31a2b7db3ae Component: engine --- .../daemon/graphdriver/devmapper/deviceset.go | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go index 802d2e6562..d721861282 100644 --- a/components/engine/daemon/graphdriver/devmapper/deviceset.go +++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go @@ -30,7 +30,9 @@ var ( DefaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024 DefaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024 DefaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024 - DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors + DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors + MaxDeviceId int = 0xffffff // 24 bit, pool limit + DeviceIdMapSz int = (MaxDeviceId + 1) / 8 ) const deviceSetMetaFile string = "deviceset-metadata" @@ -75,6 +77,7 @@ type DeviceSet struct { devicePrefix string TransactionId uint64 `json:"-"` NextDeviceId int `json:"next_device_id"` + deviceIdMap []byte // Options dataLoopbackSize int64 @@ -261,6 +264,30 @@ func (devices *DeviceSet) saveMetadata(info *DevInfo) error { return nil } +func (devices *DeviceSet) markDeviceIdUsed(deviceId int) { + var mask byte + i := deviceId % 8 + mask = 1 << uint(i) + devices.deviceIdMap[deviceId/8] = devices.deviceIdMap[deviceId/8] | mask +} + +func (devices *DeviceSet) markDeviceIdFree(deviceId int) { + var mask byte + i := deviceId % 8 + mask = ^(1 << uint(i)) + devices.deviceIdMap[deviceId/8] = devices.deviceIdMap[deviceId/8] & mask +} + +func (devices *DeviceSet) isDeviceIdFree(deviceId int) bool { + var mask byte + i := deviceId % 8 + mask = (1 << uint(i)) + if (devices.deviceIdMap[deviceId/8] & mask) != 0 { + return false + } + return true +} + func (devices *DeviceSet) lookupDevice(hash string) (*DevInfo, error) { devices.devicesLock.Lock() defer devices.devicesLock.Unlock() @@ -407,7 +434,7 @@ func (devices *DeviceSet) initMetaData() error { func (devices *DeviceSet) incNextDeviceId() { // Ids are 24bit, so wrap around - devices.NextDeviceId = (devices.NextDeviceId + 1) & 0xffffff + devices.NextDeviceId = (devices.NextDeviceId + 1) & MaxDeviceId } func (devices *DeviceSet) createDevice(deviceId *int) error { @@ -1333,6 +1360,7 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error filesystem: "ext4", doBlkDiscard: true, thinpBlockSize: DefaultThinpBlockSize, + deviceIdMap: make([]byte, DeviceIdMapSz), } foundBlkDiscard := false