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 <vgoyal@redhat.com>
This commit is contained in:
parent
359a38b26a
commit
4d39e056aa
1 changed files with 30 additions and 2 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue