Skip to content

Commit f57d563

Browse files
committed
Merge pull request moby#18686 from cpuguy83/fix_btrfs_subvol_delete_panic
Fix btrfs recursive btrfs subvol delete
2 parents b44b5bb + f9befce commit f57d563

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

daemon/graphdriver/btrfs/btrfs.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,20 +188,29 @@ func subvolDelete(dirpath, name string) error {
188188
return err
189189
}
190190
defer closeDir(dir)
191+
fullPath := path.Join(dirpath, name)
191192

192193
var args C.struct_btrfs_ioctl_vol_args
193194

194195
// walk the btrfs subvolumes
195196
walkSubvolumes := func(p string, f os.FileInfo, err error) error {
197+
if err != nil {
198+
if os.IsNotExist(err) && p != fullPath {
199+
// missing most likely because the path was a subvolume that got removed in the previous iteration
200+
// since it's gone anyway, we don't care
201+
return nil
202+
}
203+
return fmt.Errorf("error walking subvolumes: %v", err)
204+
}
196205
// we want to check children only so skip itself
197206
// it will be removed after the filepath walk anyways
198-
if f.IsDir() && p != path.Join(dirpath, name) {
207+
if f.IsDir() && p != fullPath {
199208
sv, err := isSubvolume(p)
200209
if err != nil {
201210
return fmt.Errorf("Failed to test if %s is a btrfs subvolume: %v", p, err)
202211
}
203212
if sv {
204-
if err := subvolDelete(p, f.Name()); err != nil {
213+
if err := subvolDelete(path.Dir(p), f.Name()); err != nil {
205214
return fmt.Errorf("Failed to destroy btrfs child subvolume (%s) of parent (%s): %v", p, dirpath, err)
206215
}
207216
}

daemon/graphdriver/btrfs/btrfs_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package btrfs
44

55
import (
6+
"os"
7+
"path"
68
"testing"
79

810
"github.com/docker/docker/daemon/graphdriver/graphtest"
@@ -26,6 +28,36 @@ func TestBtrfsCreateSnap(t *testing.T) {
2628
graphtest.DriverTestCreateSnap(t, "btrfs")
2729
}
2830

31+
func TestBtrfsSubvolDelete(t *testing.T) {
32+
d := graphtest.GetDriver(t, "btrfs")
33+
if err := d.Create("test", "", ""); err != nil {
34+
t.Fatal(err)
35+
}
36+
defer graphtest.PutDriver(t)
37+
38+
dir, err := d.Get("test", "")
39+
if err != nil {
40+
t.Fatal(err)
41+
}
42+
defer d.Put("test")
43+
44+
if err := subvolCreate(dir, "subvoltest"); err != nil {
45+
t.Fatal(err)
46+
}
47+
48+
if _, err := os.Stat(path.Join(dir, "subvoltest")); err != nil {
49+
t.Fatal(err)
50+
}
51+
52+
if err := d.Remove("test"); err != nil {
53+
t.Fatal(err)
54+
}
55+
56+
if _, err := os.Stat(path.Join(dir, "subvoltest")); !os.IsNotExist(err) {
57+
t.Fatalf("expected not exist error on nested subvol, got: %v", err)
58+
}
59+
}
60+
2961
func TestBtrfsTeardown(t *testing.T) {
3062
graphtest.PutDriver(t)
3163
}

0 commit comments

Comments
 (0)