Browse code

Add backing filesystem info to `docker info` command where applicable Fixes #9960

This adds the output of a "Backing Filesystem:" entry to `docker info`
to overlay, aufs, and devicemapper graphdrivers. The default list
includes a fairly complete list of common filesystem names from
linux/include/uapi/linux/magic.h, but if the backing filesystem is not
recognized, the code will simply show "<unknown>"

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>

Phil Estes authored on 2015/01/16 06:40:39
Showing 8 changed files
... ...
@@ -45,6 +45,7 @@ var (
45 45
 		graphdriver.FsMagicBtrfs,
46 46
 		graphdriver.FsMagicAufs,
47 47
 	}
48
+	backingFs = "<unknown>"
48 49
 )
49 50
 
50 51
 func init() {
... ...
@@ -60,20 +61,22 @@ type Driver struct {
60 60
 // New returns a new AUFS driver.
61 61
 // An error is returned if AUFS is not supported.
62 62
 func Init(root string, options []string) (graphdriver.Driver, error) {
63
+
63 64
 	// Try to load the aufs kernel module
64 65
 	if err := supportsAufs(); err != nil {
65 66
 		return nil, graphdriver.ErrNotSupported
66 67
 	}
67 68
 
68
-	rootdir := path.Dir(root)
69
-
70
-	var buf syscall.Statfs_t
71
-	if err := syscall.Statfs(rootdir, &buf); err != nil {
72
-		return nil, fmt.Errorf("Couldn't stat the root directory: %s", err)
69
+	fsMagic, err := graphdriver.GetFSMagic(root)
70
+	if err != nil {
71
+		return nil, err
72
+	}
73
+	if fsName, ok := graphdriver.FsNames[fsMagic]; ok {
74
+		backingFs = fsName
73 75
 	}
74 76
 
75 77
 	for _, magic := range incompatibleFsMagic {
76
-		if graphdriver.FsMagic(buf.Type) == magic {
78
+		if fsMagic == magic {
77 79
 			return nil, graphdriver.ErrIncompatibleFS
78 80
 		}
79 81
 	}
... ...
@@ -146,6 +149,7 @@ func (a *Driver) Status() [][2]string {
146 146
 	ids, _ := loadIds(path.Join(a.rootPath(), "layers"))
147 147
 	return [][2]string{
148 148
 		{"Root Dir", a.rootPath()},
149
+		{"Backing Filesystem", backingFs},
149 150
 		{"Dirs", fmt.Sprintf("%d", len(ids))},
150 151
 	}
151 152
 }
... ...
@@ -568,7 +568,7 @@ func TestStatus(t *testing.T) {
568 568
 		t.Fatal("Status should not be nil or empty")
569 569
 	}
570 570
 	rootDir := status[0]
571
-	dirs := status[1]
571
+	dirs := status[2]
572 572
 	if rootDir[0] != "Root Dir" {
573 573
 		t.Fatalf("Expected Root Dir got %s", rootDir[0])
574 574
 	}
... ...
@@ -29,7 +29,17 @@ type Driver struct {
29 29
 	home string
30 30
 }
31 31
 
32
+var backingFs = "<unknown>"
33
+
32 34
 func Init(home string, options []string) (graphdriver.Driver, error) {
35
+	fsMagic, err := graphdriver.GetFSMagic(home)
36
+	if err != nil {
37
+		return nil, err
38
+	}
39
+	if fsName, ok := graphdriver.FsNames[fsMagic]; ok {
40
+		backingFs = fsName
41
+	}
42
+
33 43
 	deviceSet, err := NewDeviceSet(home, true, options)
34 44
 	if err != nil {
35 45
 		return nil, err
... ...
@@ -57,6 +67,7 @@ func (d *Driver) Status() [][2]string {
57 57
 	status := [][2]string{
58 58
 		{"Pool Name", s.PoolName},
59 59
 		{"Pool Blocksize", fmt.Sprintf("%s", units.HumanSize(float64(s.SectorSize)))},
60
+		{"Backing Filesystem", backingFs},
60 61
 		{"Data file", s.DataFile},
61 62
 		{"Metadata file", s.MetadataFile},
62 63
 		{"Data Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Used)))},
... ...
@@ -14,8 +14,52 @@ import (
14 14
 type FsMagic uint32
15 15
 
16 16
 const (
17
-	FsMagicBtrfs = FsMagic(0x9123683E)
18
-	FsMagicAufs  = FsMagic(0x61756673)
17
+	FsMagicBtrfs       = FsMagic(0x9123683E)
18
+	FsMagicAufs        = FsMagic(0x61756673)
19
+	FsMagicExtfs       = FsMagic(0x0000EF53)
20
+	FsMagicCramfs      = FsMagic(0x28cd3d45)
21
+	FsMagicRamFs       = FsMagic(0x858458f6)
22
+	FsMagicTmpFs       = FsMagic(0x01021994)
23
+	FsMagicSquashFs    = FsMagic(0x73717368)
24
+	FsMagicNfsFs       = FsMagic(0x00006969)
25
+	FsMagicReiserFs    = FsMagic(0x52654973)
26
+	FsMagicSmbFs       = FsMagic(0x0000517B)
27
+	FsMagicJffs2Fs     = FsMagic(0x000072b6)
28
+	FsMagicUnsupported = FsMagic(0x00000000)
29
+)
30
+
31
+var (
32
+	DefaultDriver string
33
+	// All registred drivers
34
+	drivers map[string]InitFunc
35
+	// Slice of drivers that should be used in an order
36
+	priority = []string{
37
+		"aufs",
38
+		"btrfs",
39
+		"devicemapper",
40
+		"vfs",
41
+		// experimental, has to be enabled manually for now
42
+		"overlay",
43
+	}
44
+
45
+	ErrNotSupported   = errors.New("driver not supported")
46
+	ErrPrerequisites  = errors.New("prerequisites for driver not satisfied (wrong filesystem?)")
47
+	ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver")
48
+
49
+	FsNames = map[FsMagic]string{
50
+		FsMagicAufs:        "aufs",
51
+		FsMagicBtrfs:       "btrfs",
52
+		FsMagicExtfs:       "extfs",
53
+		FsMagicCramfs:      "cramfs",
54
+		FsMagicRamFs:       "ramfs",
55
+		FsMagicTmpFs:       "tmpfs",
56
+		FsMagicSquashFs:    "squashfs",
57
+		FsMagicNfsFs:       "nfs",
58
+		FsMagicReiserFs:    "reiserfs",
59
+		FsMagicSmbFs:       "smb",
60
+		FsMagicJffs2Fs:     "jffs2",
61
+		FsMagicUnsupported: "unsupported",
62
+	}
19 63
 )
20 64
 
21 65
 type InitFunc func(root string, options []string) (Driver, error)
... ...
@@ -72,25 +116,6 @@ type Driver interface {
72 72
 	DiffSize(id, parent string) (size int64, err error)
73 73
 }
74 74
 
75
-var (
76
-	DefaultDriver string
77
-	// All registred drivers
78
-	drivers map[string]InitFunc
79
-	// Slice of drivers that should be used in an order
80
-	priority = []string{
81
-		"aufs",
82
-		"btrfs",
83
-		"devicemapper",
84
-		"vfs",
85
-		// experimental, has to be enabled manually for now
86
-		"overlay",
87
-	}
88
-
89
-	ErrNotSupported   = errors.New("driver not supported")
90
-	ErrPrerequisites  = errors.New("prerequisites for driver not satisfied (wrong filesystem?)")
91
-	ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver")
92
-)
93
-
94 75
 func init() {
95 76
 	drivers = make(map[string]InitFunc)
96 77
 }
97 78
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+package graphdriver
1
+
2
+import (
3
+	"path"
4
+	"syscall"
5
+)
6
+
7
+func GetFSMagic(rootpath string) (FsMagic, error) {
8
+	var buf syscall.Statfs_t
9
+	if err := syscall.Statfs(path.Dir(rootpath), &buf); err != nil {
10
+		return 0, err
11
+	}
12
+	return FsMagic(buf.Type), nil
13
+}
0 14
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+// +build !linux
1
+
2
+package graphdriver
3
+
4
+func GetFSMagic(rootpath string) (FsMagic, error) {
5
+	return FsMagicUnsupported, nil
6
+}
... ...
@@ -90,22 +90,28 @@ type Driver struct {
90 90
 	active     map[string]*ActiveMount
91 91
 }
92 92
 
93
+var backingFs = "<unknown>"
94
+
93 95
 func init() {
94 96
 	graphdriver.Register("overlay", Init)
95 97
 }
96 98
 
97 99
 func Init(home string, options []string) (graphdriver.Driver, error) {
100
+
98 101
 	if err := supportsOverlay(); err != nil {
99 102
 		return nil, graphdriver.ErrNotSupported
100 103
 	}
101 104
 
102
-	// check if they are running over btrfs
103
-	var buf syscall.Statfs_t
104
-	if err := syscall.Statfs(path.Dir(home), &buf); err != nil {
105
+	fsMagic, err := graphdriver.GetFSMagic(home)
106
+	if err != nil {
105 107
 		return nil, err
106 108
 	}
109
+	if fsName, ok := graphdriver.FsNames[fsMagic]; ok {
110
+		backingFs = fsName
111
+	}
107 112
 
108
-	switch graphdriver.FsMagic(buf.Type) {
113
+	// check if they are running over btrfs or aufs
114
+	switch fsMagic {
109 115
 	case graphdriver.FsMagicBtrfs:
110 116
 		log.Error("'overlay' is not supported over btrfs.")
111 117
 		return nil, graphdriver.ErrIncompatibleFS
... ...
@@ -153,7 +159,9 @@ func (d *Driver) String() string {
153 153
 }
154 154
 
155 155
 func (d *Driver) Status() [][2]string {
156
-	return nil
156
+	return [][2]string{
157
+		{"Backing Filesystem", backingFs},
158
+	}
157 159
 }
158 160
 
159 161
 func (d *Driver) Cleanup() error {
... ...
@@ -1162,6 +1162,7 @@ For example:
1162 1162
     Images: 52
1163 1163
     Storage Driver: aufs
1164 1164
      Root Dir: /var/lib/docker/aufs
1165
+     Backing Filesystem: extfs
1165 1166
      Dirs: 545
1166 1167
     Execution Driver: native-0.2
1167 1168
     Kernel Version: 3.13.0-24-generic