func (devices *DeviceSet) createRegisterDevice(hash string) (*DevInfo, error) { deviceId, err := devices.getNextFreeDeviceId() if err != nil { return nil, err } if err := devices.openTransaction(hash, deviceId); err != nil { glog.V(1).Infof("Error opening transaction hash = %s deviceId = %d", hash, deviceId) devices.markDeviceIdFree(deviceId) return nil, err } for { if err := devicemapper.CreateDevice(devices.getPoolDevName(), deviceId); err != nil { if devicemapper.DeviceIdExists(err) { // Device Id already exists. This should not // happen. Now we have a mechianism to find // a free device Id. So something is not right. // Give a warning and continue. glog.Errorf("Device Id %d exists in pool but it is supposed to be unused", deviceId) deviceId, err = devices.getNextFreeDeviceId() if err != nil { return nil, err } // Save new device id into transaction devices.refreshTransaction(deviceId) continue } glog.V(1).Infof("Error creating device: %s", err) devices.markDeviceIdFree(deviceId) return nil, err } break } glog.V(1).Infof("Registering device (id %v) with FS size %v", deviceId, devices.baseFsSize) info, err := devices.registerDevice(deviceId, hash, devices.baseFsSize, devices.OpenTransactionId) if err != nil { _ = devicemapper.DeleteDevice(devices.getPoolDevName(), deviceId) devices.markDeviceIdFree(deviceId) return nil, err } if err := devices.closeTransaction(); err != nil { devices.unregisterDevice(deviceId, hash) devicemapper.DeleteDevice(devices.getPoolDevName(), deviceId) devices.markDeviceIdFree(deviceId) return nil, err } return info, nil }
func (devices *DeviceSet) deleteDevice(info *DevInfo) error { if devices.doBlkDiscard { // This is a workaround for the kernel not discarding block so // on the thin pool when we remove a thinp device, so we do it // manually if err := devices.activateDeviceIfNeeded(info); err == nil { if err := devicemapper.BlockDeviceDiscard(info.DevName()); err != nil { glog.V(1).Infof("Error discarding block on device: %s (ignoring)", err) } } } devinfo, _ := devicemapper.GetInfo(info.Name()) if devinfo != nil && devinfo.Exists != 0 { if err := devices.removeDevice(info.Name()); err != nil { glog.V(1).Infof("Error removing device: %s", err) return err } } if err := devices.openTransaction(info.Hash, info.DeviceId); err != nil { glog.V(1).Infof("Error opening transaction hash = %s deviceId = %d", "", info.DeviceId) return err } if err := devicemapper.DeleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil { glog.V(1).Infof("Error deleting device: %s", err) return err } if err := devices.unregisterDevice(info.DeviceId, info.Hash); err != nil { return err } if err := devices.closeTransaction(); err != nil { return err } devices.markDeviceIdFree(info.DeviceId) return nil }
func (devices *DeviceSet) rollbackTransaction() error { glog.V(1).Infof("Rolling back open transaction: TransactionId=%d hash=%s device_id=%d", devices.OpenTransactionId, devices.DeviceIdHash, devices.DeviceId) // A device id might have already been deleted before transaction // closed. In that case this call will fail. Just leave a message // in case of failure. if err := devicemapper.DeleteDevice(devices.getPoolDevName(), devices.DeviceId); err != nil { glog.Errorf("Unable to delete device: %s", err) } dinfo := &DevInfo{Hash: devices.DeviceIdHash} if err := devices.removeMetadata(dinfo); err != nil { glog.Errorf("Unable to remove metadata: %s", err) } else { devices.markDeviceIdFree(devices.DeviceId) } if err := devices.removeTransactionMetaData(); err != nil { glog.Errorf("Unable to remove transaction meta file %s: %s", devices.transactionMetaFile(), err) } return nil }