fix 9939: docker does not remove btrfs subvolumes when destroying container

Signed-off-by: Ma Shimiao <mashimiao.fnst@cn.fujitsu.com>
This commit is contained in:
Ma Shimiao 2015-08-05 15:10:40 +08:00 committed by Jessica Frazelle
parent 82e2dec06d
commit dea78fc2ce
1 changed files with 42 additions and 3 deletions

View File

@ -6,6 +6,7 @@ package btrfs
#include <stdlib.h>
#include <dirent.h>
#include <btrfs/ioctl.h>
#include <btrfs/ctree.h>
*/
import "C"
@ -13,6 +14,7 @@ import (
"fmt"
"os"
"path"
"path/filepath"
"syscall"
"unsafe"
@ -24,6 +26,21 @@ func init() {
graphdriver.Register("btrfs", Init)
}
func is_subvolume(dirpath string) (bool, error) {
rootdir := path.Dir(dirpath)
var bufStat syscall.Stat_t
if err := syscall.Lstat(rootdir, &bufStat); err != nil {
return false, err
}
if bufStat.Ino != C.BTRFS_FIRST_FREE_OBJECTID {
return false, nil
}
return true, nil
}
// Init returns a new BTRFS driver.
// An error is returned if BTRFS is not supported.
func Init(home string, options []string) (graphdriver.Driver, error) {
@ -160,18 +177,40 @@ func subvolSnapshot(src, dest, name string) error {
return nil
}
func subvolDelete(path, name string) error {
dir, err := openDir(path)
func subvolDelete(dirpath, name string) error {
dir, err := openDir(dirpath)
if err != nil {
return err
}
defer closeDir(dir)
var args C.struct_btrfs_ioctl_vol_args
filepath.Walk(dirpath,
func(dirpath string, f os.FileInfo, err error) error {
if f.IsDir() {
isSubvolumes, err := is_subvolume(path.Join(dirpath, f.Name()))
if err != nil {
return err
}
if isSubvolumes {
for i, c := range []byte(f.Name()) {
args.name[i] = C.char(c)
}
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY,
uintptr(unsafe.Pointer(&args)))
if errno != 0 {
return fmt.Errorf("Failed to destroy btrfs snapshot: %v", errno.Error())
}
}
return nil
}
return nil
})
for i, c := range []byte(name) {
args.name[i] = C.char(c)
}
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY,
uintptr(unsafe.Pointer(&args)))
if errno != 0 {