mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #41 from alexlarsson/dm-plugin-device-tool
Update docker-device-tool
This commit is contained in:
commit
3e0a5ac48b
6 changed files with 446 additions and 100 deletions
170
contrib/docker-device-tool/device_tool.go
Normal file
170
contrib/docker-device-tool/device_tool.go
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"github.com/dotcloud/docker/graphdriver/devmapper"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: %s <flags> [status] | [list] | [device id] | [resize new-pool-size] | [snap new-id base-id] | [remove id] | [mount id mountpoint]\n", os.Args[0])
|
||||||
|
flag.PrintDefaults()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func byteSizeFromString(arg string) (int64, error) {
|
||||||
|
digits := ""
|
||||||
|
rest := ""
|
||||||
|
last := strings.LastIndexAny(arg, "0123456789")
|
||||||
|
if last >= 0 {
|
||||||
|
digits = arg[:last+1]
|
||||||
|
rest = arg[last+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := strconv.ParseInt(digits, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rest = strings.ToLower(strings.TrimSpace(rest))
|
||||||
|
|
||||||
|
var multiplier int64 = 1
|
||||||
|
switch rest {
|
||||||
|
case "":
|
||||||
|
multiplier = 1
|
||||||
|
case "k", "kb":
|
||||||
|
multiplier = 1024
|
||||||
|
case "m", "mb":
|
||||||
|
multiplier = 1024 * 1024
|
||||||
|
case "g", "gb":
|
||||||
|
multiplier = 1024 * 1024 * 1024
|
||||||
|
case "t", "tb":
|
||||||
|
multiplier = 1024 * 1024 * 1024 * 1024
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("Unknown size unit: %s", rest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return val * multiplier, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag.NArg() < 1 {
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
args := flag.Args()
|
||||||
|
|
||||||
|
home := path.Join(*root, "devicemapper")
|
||||||
|
devices, err := devmapper.NewDeviceSet(home, false)
|
||||||
|
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 resizeing 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 := devices.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], false)
|
||||||
|
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
|
||||||
|
}
|
|
@ -57,6 +57,16 @@ type Status struct {
|
||||||
MetadataLoopback string
|
MetadataLoopback string
|
||||||
Data DiskUsage
|
Data DiskUsage
|
||||||
Metadata DiskUsage
|
Metadata DiskUsage
|
||||||
|
SectorSize uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type DevStatus struct {
|
||||||
|
DeviceId int
|
||||||
|
Size uint64
|
||||||
|
TransactionId uint64
|
||||||
|
SizeInSectors uint64
|
||||||
|
MappedSectors uint64
|
||||||
|
HighestMappedSector uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDevName(name string) string {
|
func getDevName(name string) string {
|
||||||
|
@ -357,13 +367,90 @@ func minor(device uint64) uint64 {
|
||||||
return (device & 0xff) | ((device >> 12) & 0xfff00)
|
return (device & 0xff) | ((device >> 12) & 0xfff00)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) initDevmapper() error {
|
func (devices *DeviceSet) ResizePool(size int64) error {
|
||||||
|
dirname := devices.loopbackDir()
|
||||||
|
datafilename := path.Join(dirname, "data")
|
||||||
|
metadatafilename := path.Join(dirname, "metadata")
|
||||||
|
|
||||||
|
datafile, err := os.OpenFile(datafilename, os.O_RDWR, 0)
|
||||||
|
if datafile == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer datafile.Close()
|
||||||
|
|
||||||
|
fi, err := datafile.Stat()
|
||||||
|
if fi == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.Size() > size {
|
||||||
|
return fmt.Errorf("Can't shrink file")
|
||||||
|
}
|
||||||
|
|
||||||
|
dataloopback := FindLoopDeviceFor(datafile)
|
||||||
|
if dataloopback == nil {
|
||||||
|
return fmt.Errorf("Unable to find loopback mount for: %s", datafilename)
|
||||||
|
}
|
||||||
|
defer dataloopback.Close()
|
||||||
|
|
||||||
|
metadatafile, err := os.OpenFile(metadatafilename, os.O_RDWR, 0)
|
||||||
|
if metadatafile == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer metadatafile.Close()
|
||||||
|
|
||||||
|
metadataloopback := FindLoopDeviceFor(metadatafile)
|
||||||
|
if metadataloopback == nil {
|
||||||
|
return fmt.Errorf("Unable to find loopback mount for: %s", metadatafilename)
|
||||||
|
}
|
||||||
|
defer metadataloopback.Close()
|
||||||
|
|
||||||
|
// Grow loopback file
|
||||||
|
if err := datafile.Truncate(size); err != nil {
|
||||||
|
return fmt.Errorf("Unable to grow loopback file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload size for loopback device
|
||||||
|
if err := LoopbackSetCapacity(dataloopback); err != nil {
|
||||||
|
return fmt.Errorf("Unable to update loopback capacity: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suspend the pool
|
||||||
|
if err := suspendDevice(devices.getPoolName()); err != nil {
|
||||||
|
return fmt.Errorf("Unable to suspend pool: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload with the new block sizes
|
||||||
|
if err := reloadPool(devices.getPoolName(), dataloopback, metadataloopback); err != nil {
|
||||||
|
return fmt.Errorf("Unable to reload pool: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resume the pool
|
||||||
|
if err := resumeDevice(devices.getPoolName()); err != nil {
|
||||||
|
return fmt.Errorf("Unable to resume pool: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
logInit(devices)
|
logInit(devices)
|
||||||
|
|
||||||
// Make sure the sparse images exist in <root>/devicemapper/data and
|
// Make sure the sparse images exist in <root>/devicemapper/data and
|
||||||
// <root>/devicemapper/metadata
|
// <root>/devicemapper/metadata
|
||||||
|
|
||||||
createdLoopback := !devices.hasImage("data") || !devices.hasImage("metadata")
|
hasData := devices.hasImage("data")
|
||||||
|
hasMetadata := devices.hasImage("metadata")
|
||||||
|
|
||||||
|
if !doInit && !hasData {
|
||||||
|
return fmt.Errorf("Looback data file not found %s")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doInit && !hasMetadata {
|
||||||
|
return fmt.Errorf("Looback metadata file not found %s")
|
||||||
|
}
|
||||||
|
|
||||||
|
createdLoopback := !hasData || !hasMetadata
|
||||||
data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
|
data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
||||||
|
@ -438,10 +525,12 @@ func (devices *DeviceSet) initDevmapper() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the base image
|
// Setup the base image
|
||||||
|
if doInit {
|
||||||
if err := devices.setupBaseImage(); err != nil {
|
if err := devices.setupBaseImage(); err != nil {
|
||||||
utils.Debugf("Error device setupBaseImage: %s\n", err)
|
utils.Debugf("Error device setupBaseImage: %s\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -757,6 +846,69 @@ func (devices *DeviceSet) setInitialized(hash string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) List() []string {
|
||||||
|
devices.Lock()
|
||||||
|
defer devices.Unlock()
|
||||||
|
|
||||||
|
ids := make([]string, len(devices.Devices))
|
||||||
|
i := 0
|
||||||
|
for k := range devices.Devices {
|
||||||
|
ids[i] = k
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) {
|
||||||
|
var params string
|
||||||
|
_, sizeInSectors, _, params, err = getStatus(devName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = fmt.Sscanf(params, "%d %d", &mappedSectors, &highestMappedSector); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) {
|
||||||
|
devices.Lock()
|
||||||
|
defer devices.Unlock()
|
||||||
|
|
||||||
|
info := devices.Devices[hash]
|
||||||
|
if info == nil {
|
||||||
|
return nil, fmt.Errorf("No device %s", hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
status := &DevStatus{
|
||||||
|
DeviceId: info.DeviceId,
|
||||||
|
Size: info.Size,
|
||||||
|
TransactionId: info.TransactionId,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := devices.activateDeviceIfNeeded(hash); err != nil {
|
||||||
|
return nil, fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
status.SizeInSectors = sizeInSectors
|
||||||
|
status.MappedSectors = mappedSectors
|
||||||
|
status.HighestMappedSector = highestMappedSector
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (devices *DeviceSet) poolStatus() (totalSizeInSectors, transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64, err error) {
|
||||||
|
var params string
|
||||||
|
if _, totalSizeInSectors, _, params, err = getStatus(devices.getPoolName()); err == nil {
|
||||||
|
_, err = fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) Status() *Status {
|
func (devices *DeviceSet) Status() *Status {
|
||||||
devices.Lock()
|
devices.Lock()
|
||||||
defer devices.Unlock()
|
defer devices.Unlock()
|
||||||
|
@ -767,10 +919,8 @@ func (devices *DeviceSet) Status() *Status {
|
||||||
status.DataLoopback = path.Join(devices.loopbackDir(), "data")
|
status.DataLoopback = path.Join(devices.loopbackDir(), "data")
|
||||||
status.MetadataLoopback = path.Join(devices.loopbackDir(), "metadata")
|
status.MetadataLoopback = path.Join(devices.loopbackDir(), "metadata")
|
||||||
|
|
||||||
_, totalSizeInSectors, _, params, err := getStatus(devices.getPoolName())
|
totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64
|
|
||||||
if _, err := fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal); err == nil {
|
|
||||||
// Convert from blocks to bytes
|
// Convert from blocks to bytes
|
||||||
blockSizeInSectors := totalSizeInSectors / dataTotal
|
blockSizeInSectors := totalSizeInSectors / dataTotal
|
||||||
|
|
||||||
|
@ -780,13 +930,14 @@ func (devices *DeviceSet) Status() *Status {
|
||||||
// metadata blocks are always 4k
|
// metadata blocks are always 4k
|
||||||
status.Metadata.Used = metadataUsed * 4096
|
status.Metadata.Used = metadataUsed * 4096
|
||||||
status.Metadata.Total = metadataTotal * 4096
|
status.Metadata.Total = metadataTotal * 4096
|
||||||
}
|
|
||||||
|
status.SectorSize = blockSizeInSectors * 512
|
||||||
}
|
}
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeviceSet(root string) (*DeviceSet, error) {
|
func NewDeviceSet(root string, doInit bool) (*DeviceSet, error) {
|
||||||
SetDevDir("/dev")
|
SetDevDir("/dev")
|
||||||
|
|
||||||
devices := &DeviceSet{
|
devices := &DeviceSet{
|
||||||
|
@ -795,7 +946,7 @@ func NewDeviceSet(root string) (*DeviceSet, error) {
|
||||||
activeMounts: make(map[string]int),
|
activeMounts: make(map[string]int),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := devices.initDevmapper(); err != nil {
|
if err := devices.initDevmapper(doInit); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DevmapperLogger interface {
|
type DevmapperLogger interface {
|
||||||
|
@ -59,6 +60,8 @@ var (
|
||||||
ErrCreateRemoveTask = errors.New("Can't create task of type DeviceRemove")
|
ErrCreateRemoveTask = errors.New("Can't create task of type DeviceRemove")
|
||||||
ErrRunRemoveDevice = errors.New("running removeDevice failed")
|
ErrRunRemoveDevice = errors.New("running removeDevice failed")
|
||||||
ErrInvalidAddNode = errors.New("Invalide AddNoce type")
|
ErrInvalidAddNode = errors.New("Invalide AddNoce type")
|
||||||
|
ErrGetLoopbackBackingFile = errors.New("Unable to get loopback backing file")
|
||||||
|
ErrLoopbackSetCapacity = errors.New("Unable set loopback capacity")
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -186,6 +189,55 @@ func AttachLoopDevice(filename string) (*os.File, error) {
|
||||||
return os.NewFile(uintptr(fd), res), nil
|
return os.NewFile(uintptr(fd), res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
|
||||||
|
dev, inode, err := dmGetLoopbackBackingFile(file.Fd())
|
||||||
|
if err != 0 {
|
||||||
|
return 0, 0, ErrGetLoopbackBackingFile
|
||||||
|
}
|
||||||
|
return dev, inode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoopbackSetCapacity(file *os.File) error {
|
||||||
|
err := dmLoopbackSetCapacity(file.Fd())
|
||||||
|
if err != 0 {
|
||||||
|
return ErrLoopbackSetCapacity
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindLoopDeviceFor(file *os.File) *os.File {
|
||||||
|
stat, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
targetInode := stat.Sys().(*syscall.Stat_t).Ino
|
||||||
|
targetDevice := stat.Sys().(*syscall.Stat_t).Dev
|
||||||
|
|
||||||
|
for i := 0; true; i++ {
|
||||||
|
path := fmt.Sprintf("/dev/loop%d", i)
|
||||||
|
|
||||||
|
file, err := os.OpenFile(path, os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore all errors until the first not-exist
|
||||||
|
// we want to continue looking for the file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dev, inode, err := getLoopbackBackingFile(file)
|
||||||
|
if err == nil && dev == targetDevice && inode == targetInode {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func UdevWait(cookie uint) error {
|
func UdevWait(cookie uint) error {
|
||||||
if res := DmUdevWait(cookie); res != 1 {
|
if res := DmUdevWait(cookie); res != 1 {
|
||||||
utils.Debugf("Failed to wait on udev cookie %d", cookie)
|
utils.Debugf("Failed to wait on udev cookie %d", cookie)
|
||||||
|
@ -276,6 +328,29 @@ func createPool(poolName string, dataFile *os.File, metadataFile *os.File) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reloadPool(poolName string, dataFile *os.File, metadataFile *os.File) error {
|
||||||
|
task, err := createTask(DeviceReload, poolName)
|
||||||
|
if task == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
size, err := GetBlockDeviceSize(dataFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Can't get data size")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := metadataFile.Name() + " " + dataFile.Name() + " 128 32768"
|
||||||
|
if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
|
||||||
|
return fmt.Errorf("Can't add target")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := task.Run(); err != nil {
|
||||||
|
return fmt.Errorf("Error running DeviceCreate")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func createTask(t TaskType, name string) (*Task, error) {
|
func createTask(t TaskType, name string) (*Task, error) {
|
||||||
task := TaskCreate(t)
|
task := TaskCreate(t)
|
||||||
if task == nil {
|
if task == nil {
|
||||||
|
|
|
@ -239,6 +239,18 @@ func dmTaskAddTargetFct(task *CDmTask,
|
||||||
C.uint64_t(start), C.uint64_t(size), Cttype, Cparams))
|
C.uint64_t(start), C.uint64_t(size), Cttype, Cparams))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dmGetLoopbackBackingFile(fd uintptr) (uint64, uint64, syscall.Errno) {
|
||||||
|
var lo64 C.struct_loop_info64
|
||||||
|
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, C.LOOP_GET_STATUS64,
|
||||||
|
uintptr(unsafe.Pointer(&lo64)))
|
||||||
|
return uint64(lo64.lo_device), uint64(lo64.lo_inode), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func dmLoopbackSetCapacity(fd uintptr) syscall.Errno {
|
||||||
|
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, C.LOOP_SET_CAPACITY, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func dmGetBlockSizeFct(fd uintptr) (int64, syscall.Errno) {
|
func dmGetBlockSizeFct(fd uintptr) (int64, syscall.Errno) {
|
||||||
var size int64
|
var size int64
|
||||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, C.BLKGETSIZE64,
|
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, C.BLKGETSIZE64,
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/dotcloud/docker/devmapper"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
fmt.Printf("Usage: %s [snap new-id base-id] | [remove id] | [mount id mountpoint]\n", os.Args[0])
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
devices := devmapper.NewDeviceSet("/var/lib/docker")
|
|
||||||
|
|
||||||
if len(os.Args) < 2 {
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := os.Args[1]
|
|
||||||
if cmd == "snap" {
|
|
||||||
if len(os.Args) < 4 {
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
err := devices.AddDevice(os.Args[2], os.Args[3])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Can't create snap device: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else if cmd == "remove" {
|
|
||||||
if len(os.Args) < 3 {
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
err := devices.RemoveDevice(os.Args[2])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Can't remove device: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else if cmd == "mount" {
|
|
||||||
if len(os.Args) < 4 {
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
err := devices.MountDevice(os.Args[2], os.Args[3])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Can't create snap device: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Unknown command %s\n", cmd)
|
|
||||||
if len(os.Args) < 4 {
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ type Driver struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(home string) (graphdriver.Driver, error) {
|
func Init(home string) (graphdriver.Driver, error) {
|
||||||
deviceSet, err := NewDeviceSet(home)
|
deviceSet, err := NewDeviceSet(home, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue