Skip to content

Commit dea78fc

Browse files
Ma Shimiaojessfraz
authored andcommitted
fix 9939: docker does not remove btrfs subvolumes when destroying container
Signed-off-by: Ma Shimiao <mashimiao.fnst@cn.fujitsu.com>
1 parent 82e2dec commit dea78fc

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

daemon/graphdriver/btrfs/btrfs.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ package btrfs
66
#include <stdlib.h>
77
#include <dirent.h>
88
#include <btrfs/ioctl.h>
9+
#include <btrfs/ctree.h>
910
*/
1011
import "C"
1112

1213
import (
1314
"fmt"
1415
"os"
1516
"path"
17+
"path/filepath"
1618
"syscall"
1719
"unsafe"
1820

@@ -24,6 +26,21 @@ func init() {
2426
graphdriver.Register("btrfs", Init)
2527
}
2628

29+
func is_subvolume(dirpath string) (bool, error) {
30+
rootdir := path.Dir(dirpath)
31+
32+
var bufStat syscall.Stat_t
33+
if err := syscall.Lstat(rootdir, &bufStat); err != nil {
34+
return false, err
35+
}
36+
37+
if bufStat.Ino != C.BTRFS_FIRST_FREE_OBJECTID {
38+
return false, nil
39+
}
40+
41+
return true, nil
42+
}
43+
2744
// Init returns a new BTRFS driver.
2845
// An error is returned if BTRFS is not supported.
2946
func Init(home string, options []string) (graphdriver.Driver, error) {
@@ -160,18 +177,40 @@ func subvolSnapshot(src, dest, name string) error {
160177
return nil
161178
}
162179

163-
func subvolDelete(path, name string) error {
164-
dir, err := openDir(path)
180+
func subvolDelete(dirpath, name string) error {
181+
dir, err := openDir(dirpath)
165182
if err != nil {
166183
return err
167184
}
168185
defer closeDir(dir)
169186

170187
var args C.struct_btrfs_ioctl_vol_args
188+
189+
filepath.Walk(dirpath,
190+
func(dirpath string, f os.FileInfo, err error) error {
191+
if f.IsDir() {
192+
isSubvolumes, err := is_subvolume(path.Join(dirpath, f.Name()))
193+
if err != nil {
194+
return err
195+
}
196+
if isSubvolumes {
197+
for i, c := range []byte(f.Name()) {
198+
args.name[i] = C.char(c)
199+
}
200+
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY,
201+
uintptr(unsafe.Pointer(&args)))
202+
if errno != 0 {
203+
return fmt.Errorf("Failed to destroy btrfs snapshot: %v", errno.Error())
204+
}
205+
}
206+
return nil
207+
}
208+
return nil
209+
})
210+
171211
for i, c := range []byte(name) {
172212
args.name[i] = C.char(c)
173213
}
174-
175214
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_SNAP_DESTROY,
176215
uintptr(unsafe.Pointer(&args)))
177216
if errno != 0 {

0 commit comments

Comments
 (0)