func (d *Driver) deactivatePool() error { dev := d.Device volumeIDs := dev.listVolumeIDs() for _, id := range volumeIDs { volume := dev.loadVolume(id) if volume == nil { return generateError(logrus.Fields{ LOG_FIELD_VOLUME: id, }, "Cannot find volume") } if err := devicemapper.RemoveDevice(id); err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_EVENT: LOG_EVENT_ACTIVATE, LOG_FIELD_VOLUME: id, }).Debug("Deactivated volume device") } if err := removePool(dev.ThinpoolDevice); err != nil { return err } log.Debug("Deactivate the pool ", dev.ThinpoolDevice) return nil }
// Issues the underlying dm remove operation and then waits // for it to finish. func (devices *DeviceSet) removeDeviceAndWait(devname string) error { var err error for i := 0; i < 1000; i++ { err = devicemapper.RemoveDevice(devname) if err == nil { break } if err != devicemapper.ErrBusy { return err } // If we see EBUSY it may be a transient error, // sleep a bit a retry a few times. devices.Unlock() time.Sleep(10 * time.Millisecond) devices.Lock() } if err != nil { return err } if err := devices.waitRemove(devname); err != nil { return err } return nil }
func removePool(poolName string) error { err := devicemapper.RemoveDevice(poolName) if err != nil { return err } log.Debugln("Removed pool /dev/mapper/" + poolName) return nil }
func (d *Driver) DeleteVolume(id string) error { var err error volume := d.loadVolume(id) if volume == nil { return generateError(logrus.Fields{ LOG_FIELD_VOLUME: id, }, "cannot find volume") } if len(volume.Snapshots) != 0 { for snapshotUUID := range volume.Snapshots { if err = d.DeleteSnapshot(snapshotUUID, volume.UUID); err != nil { return generateError(logrus.Fields{ LOG_FIELD_VOLUME: volume.UUID, LOG_FIELD_SNAPSHOT: snapshotUUID, }, "cannot remove an snapshot of volume, as part of deletion of volume") } } } if err = devicemapper.RemoveDevice(id); err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_START, LOG_FIELD_EVENT: LOG_EVENT_REMOVE, LOG_FIELD_OBJECT: LOG_OBJECT_VOLUME, LOG_FIELD_VOLUME: id, DM_LOG_FIELD_VOLUME_DEVID: volume.DevID, }).Debugf("Deleting device") err = devicemapper.DeleteDevice(d.ThinpoolDevice, volume.DevID) if err != nil { return err } if volume.Base != "" { image := d.loadImage(volume.Base) if image == nil { return generateError(logrus.Fields{ LOG_FIELD_IMAGE: volume.Base, }, "Cannot find volume's base image") } if _, exists := image.VolumeRef[volume.UUID]; !exists { return generateError(logrus.Fields{ LOG_FIELD_IMAGE: volume.Base, LOG_FIELD_VOLUME: volume.UUID, }, "Volume's base image doesn't refer volumev") } delete(image.VolumeRef, volume.UUID) } if err := d.deleteVolume(id); err != nil { return err } return nil }
func (devices *DeviceSet) deactivatePool() error { log.Debugf("[devmapper] deactivatePool()") defer log.Debugf("[devmapper] deactivatePool END") devname := devices.getPoolDevName() devinfo, err := devicemapper.GetInfo(devname) if err != nil { return err } if d, err := devicemapper.GetDeps(devname); err == nil { // Access to more Debug output log.Debugf("[devmapper] devicemapper.GetDeps() %s: %#v", devname, d) } if devinfo.Exists != 0 { return devicemapper.RemoveDevice(devname) } return nil }
func (d *Driver) removeDevice(name string) error { if err := devicemapper.BlockDeviceDiscard(name); err != nil { log.Debugf("Error %s when discarding %v, ignored", err, name) } for i := 0; i < 200; i++ { err := devicemapper.RemoveDevice(name) if err == nil { break } if err != devicemapper.ErrBusy { return err } // If we see EBUSY it may be a transient error, // sleep a bit a retry a few times. time.Sleep(100 * time.Millisecond) } return nil }
func (d *Driver) CloseSnapshot(id, volumeID string) error { snapshot, volume, err := d.getSnapshotAndVolume(id, volumeID) if err != nil { return err } log.WithFields(logrus.Fields{ LOG_FIELD_REASON: LOG_REASON_START, LOG_FIELD_EVENT: LOG_EVENT_DEACTIVATE, LOG_FIELD_OBJECT: LOG_OBJECT_SNAPSHOT, LOG_FIELD_SNAPSHOT: id, }).Debug() if err := devicemapper.RemoveDevice(id); err != nil { return err } snapshot.Activated = false return util.ObjectSave(volume) }
// Issues the underlying dm remove operation. func (devices *DeviceSet) removeDevice(devname string) error { var err error logrus.Debugf("[devmapper] removeDevice START(%s)", devname) defer logrus.Debugf("[devmapper] removeDevice END(%s)", devname) for i := 0; i < 200; i++ { err = devicemapper.RemoveDevice(devname) if err == nil { break } if err != devicemapper.ErrBusy { return err } // If we see EBUSY it may be a transient error, // sleep a bit a retry a few times. devices.Unlock() time.Sleep(100 * time.Millisecond) devices.Lock() } return err }
func main() { root := flag.String("r", "/var/lib/docker", "Docker root dir") flDebug := flag.Bool("D", false, "Debug mode") flag.Parse() if *flDebug { os.Setenv("DEBUG", "1") logrus.SetLevel(logrus.DebugLevel) } if flag.NArg() < 1 { usage() } args := flag.Args() home := path.Join(*root, "devicemapper") devices, err := devmapper.NewDeviceSet(home, false, nil, nil, nil) if err != nil { fmt.Println("Can't initialize device mapper: ", err) os.Exit(1) } switch args[0] { case "status": status := devices.Status() fmt.Printf("Pool name: %s\n", status.PoolName) fmt.Printf("Data Loopback file: %s\n", status.DataLoopback) fmt.Printf("Metadata Loopback file: %s\n", status.MetadataLoopback) fmt.Printf("Sector size: %d\n", status.SectorSize) fmt.Printf("Data use: %d of %d (%.1f %%)\n", status.Data.Used, status.Data.Total, 100.0*float64(status.Data.Used)/float64(status.Data.Total)) fmt.Printf("Metadata use: %d of %d (%.1f %%)\n", status.Metadata.Used, status.Metadata.Total, 100.0*float64(status.Metadata.Used)/float64(status.Metadata.Total)) break case "list": ids := devices.List() sort.Strings(ids) for _, id := range ids { fmt.Println(id) } break case "device": if flag.NArg() < 2 { usage() } status, err := devices.GetDeviceStatus(args[1]) if err != nil { fmt.Println("Can't get device info: ", err) os.Exit(1) } fmt.Printf("Id: %d\n", status.DeviceID) fmt.Printf("Size: %d\n", status.Size) fmt.Printf("Transaction Id: %d\n", status.TransactionID) fmt.Printf("Size in Sectors: %d\n", status.SizeInSectors) fmt.Printf("Mapped Sectors: %d\n", status.MappedSectors) fmt.Printf("Highest Mapped Sector: %d\n", status.HighestMappedSector) break case "resize": if flag.NArg() < 2 { usage() } size, err := byteSizeFromString(args[1]) if err != nil { fmt.Println("Invalid size: ", err) os.Exit(1) } err = devices.ResizePool(size) if err != nil { fmt.Println("Error resizing pool: ", err) os.Exit(1) } break case "snap": if flag.NArg() < 3 { usage() } err := devices.AddDevice(args[1], args[2]) if err != nil { fmt.Println("Can't create snap device: ", err) os.Exit(1) } break case "remove": if flag.NArg() < 2 { usage() } err := devicemapper.RemoveDevice(args[1]) if err != nil { fmt.Println("Can't remove device: ", err) os.Exit(1) } break case "mount": if flag.NArg() < 3 { usage() } err := devices.MountDevice(args[1], args[2], "") if err != nil { fmt.Println("Can't create snap device: ", err) os.Exit(1) } break default: fmt.Printf("Unknown command %s\n", args[0]) usage() os.Exit(1) } return }