mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #15801 from jfrazelle/btrfs-rm-subvolume-recursion
remove btrfs subvolumes when destroying containers (recursive)
This commit is contained in:
commit
459c2c66c3
4 changed files with 48 additions and 6 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
FROM debian:wheezy-backports
|
FROM debian:wheezy-backports
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools/wheezy-backports build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|
|
@ -73,6 +73,12 @@ for version in "${versions[@]}"; do
|
||||||
extraBuildTags+=' exclude_graphdriver_btrfs'
|
extraBuildTags+=' exclude_graphdriver_btrfs'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$suite" = 'wheezy' ]; then
|
||||||
|
# pull btrfs-toold from backports
|
||||||
|
backports="/$suite-backports"
|
||||||
|
packages=( "${packages[@]/btrfs-tools/btrfs-tools$backports}" )
|
||||||
|
fi
|
||||||
|
|
||||||
echo "RUN apt-get update && apt-get install -y ${packages[*]} --no-install-recommends && rm -rf /var/lib/apt/lists/*" >> "$version/Dockerfile"
|
echo "RUN apt-get update && apt-get install -y ${packages[*]} --no-install-recommends && rm -rf /var/lib/apt/lists/*" >> "$version/Dockerfile"
|
||||||
|
|
||||||
echo >> "$version/Dockerfile"
|
echo >> "$version/Dockerfile"
|
||||||
|
|
|
@ -6,6 +6,7 @@ package btrfs
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <btrfs/ioctl.h>
|
#include <btrfs/ioctl.h>
|
||||||
|
#include <btrfs/ctree.h>
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -160,22 +162,55 @@ func subvolSnapshot(src, dest, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func subvolDelete(path, name string) error {
|
func isSubvolume(p string) (bool, error) {
|
||||||
dir, err := openDir(path)
|
var bufStat syscall.Stat_t
|
||||||
|
if err := syscall.Lstat(p, &bufStat); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if it is a btrfs subvolume
|
||||||
|
return bufStat.Ino == C.BTRFS_FIRST_FREE_OBJECTID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func subvolDelete(dirpath, name string) error {
|
||||||
|
dir, err := openDir(dirpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer closeDir(dir)
|
defer closeDir(dir)
|
||||||
|
|
||||||
var args C.struct_btrfs_ioctl_vol_args
|
var args C.struct_btrfs_ioctl_vol_args
|
||||||
|
|
||||||
|
// walk the btrfs subvolumes
|
||||||
|
walkSubvolumes := func(p string, f os.FileInfo, err error) error {
|
||||||
|
// we want to check children only so skip itself
|
||||||
|
// it will be removed after the filepath walk anyways
|
||||||
|
if f.IsDir() && p != path.Join(dirpath, name) {
|
||||||
|
sv, err := isSubvolume(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to test if %s is a btrfs subvolume: %v", p, err)
|
||||||
|
}
|
||||||
|
if sv {
|
||||||
|
if err := subvolDelete(p, f.Name()); err != nil {
|
||||||
|
return fmt.Errorf("Failed to destroy btrfs child subvolume (%s) of parent (%s): %v", p, dirpath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := filepath.Walk(path.Join(dirpath, name), walkSubvolumes); err != nil {
|
||||||
|
return fmt.Errorf("Recursively walking subvolumes for %s failed: %v", dirpath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// all subvolumes have been removed
|
||||||
|
// now remove the one originally passed in
|
||||||
for i, c := range []byte(name) {
|
for i, c := range []byte(name) {
|
||||||
args.name[i] = C.char(c)
|
args.name[i] = C.char(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY,
|
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY,
|
||||||
uintptr(unsafe.Pointer(&args)))
|
uintptr(unsafe.Pointer(&args)))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return fmt.Errorf("Failed to destroy btrfs snapshot: %v", errno.Error())
|
return fmt.Errorf("Failed to destroy btrfs snapshot %s for %s: %v", dirpath, name, errno.Error())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
package btrfs
|
package btrfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/daemon/graphdriver/graphtest"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/daemon/graphdriver/graphtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This avoids creating a new driver for each test if all tests are run
|
// This avoids creating a new driver for each test if all tests are run
|
||||||
|
|
Loading…
Reference in a new issue