@@ -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*/
1011import "C"
1112
1213import (
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.
2946func 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