Browse code

devicemapper: Don't mount in Create()

We used to mount in Create() to be able to create a few files that
needs to be in each device. However, this mount is problematic for
selinux, as we need to set the mount label at mount-time, and it
is not known at the time of Create().

This change just moves the file creation to first Get() call and
drops the mount from Create(). Additionally, this lets us remove
some complexities we had to avoid an extra unmount+mount cycle.

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)

Alexander Larsson authored on 2014/04/23 20:50:53
Showing 3 changed files
... ...
@@ -35,12 +35,6 @@ type DevInfo struct {
35 35
 
36 36
 	mountCount int    `json:"-"`
37 37
 	mountPath  string `json:"-"`
38
-	// A floating mount means one reference is not owned and
39
-	// will be stolen by the next mount. This allows us to
40
-	// avoid unmounting directly after creation before the
41
-	// first get (since we need to mount to set up the device
42
-	// a bit first).
43
-	floating bool `json:"-"`
44 38
 
45 39
 	// The global DeviceSet lock guarantees that we serialize all
46 40
 	// the calls to libdevmapper (which is not threadsafe), but we
... ...
@@ -94,14 +88,6 @@ type DevStatus struct {
94 94
 	HighestMappedSector uint64
95 95
 }
96 96
 
97
-type UnmountMode int
98
-
99
-const (
100
-	UnmountRegular UnmountMode = iota
101
-	UnmountFloat
102
-	UnmountSink
103
-)
104
-
105 97
 func getDevName(name string) string {
106 98
 	return "/dev/mapper/" + name
107 99
 }
... ...
@@ -876,12 +862,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) erro
876 876
 			return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
877 877
 		}
878 878
 
879
-		if info.floating {
880
-			// Steal floating ref
881
-			info.floating = false
882
-		} else {
883
-			info.mountCount++
884
-		}
879
+		info.mountCount++
885 880
 		return nil
886 881
 	}
887 882
 
... ...
@@ -903,13 +884,12 @@ func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) erro
903 903
 
904 904
 	info.mountCount = 1
905 905
 	info.mountPath = path
906
-	info.floating = false
907 906
 
908 907
 	return devices.setInitialized(info)
909 908
 }
910 909
 
911
-func (devices *DeviceSet) UnmountDevice(hash string, mode UnmountMode) error {
912
-	utils.Debugf("[devmapper] UnmountDevice(hash=%s, mode=%d)", hash, mode)
910
+func (devices *DeviceSet) UnmountDevice(hash string) error {
911
+	utils.Debugf("[devmapper] UnmountDevice(hash=%s)", hash)
913 912
 	defer utils.Debugf("[devmapper] UnmountDevice END")
914 913
 
915 914
 	info, err := devices.lookupDevice(hash)
... ...
@@ -923,24 +903,6 @@ func (devices *DeviceSet) UnmountDevice(hash string, mode UnmountMode) error {
923 923
 	devices.Lock()
924 924
 	defer devices.Unlock()
925 925
 
926
-	if mode == UnmountFloat {
927
-		if info.floating {
928
-			return fmt.Errorf("UnmountDevice: can't float floating reference %s\n", hash)
929
-		}
930
-
931
-		// Leave this reference floating
932
-		info.floating = true
933
-		return nil
934
-	}
935
-
936
-	if mode == UnmountSink {
937
-		if !info.floating {
938
-			// Someone already sunk this
939
-			return nil
940
-		}
941
-		// Otherwise, treat this as a regular unmount
942
-	}
943
-
944 926
 	if info.mountCount == 0 {
945 927
 		return fmt.Errorf("UnmountDevice: device not-mounted id %s\n", hash)
946 928
 	}
... ...
@@ -64,26 +64,6 @@ func (d *Driver) Create(id, parent string, mountLabel string) error {
64 64
 	if err := d.DeviceSet.AddDevice(id, parent); err != nil {
65 65
 		return err
66 66
 	}
67
-	mp := path.Join(d.home, "mnt", id)
68
-	if err := d.mount(id, mp); err != nil {
69
-		return err
70
-	}
71
-
72
-	if err := osMkdirAll(path.Join(mp, "rootfs"), 0755); err != nil && !osIsExist(err) {
73
-		return err
74
-	}
75
-
76
-	// Create an "id" file with the container/image id in it to help reconscruct this in case
77
-	// of later problems
78
-	if err := ioutil.WriteFile(path.Join(mp, "id"), []byte(id), 0600); err != nil {
79
-		return err
80
-	}
81
-
82
-	// We float this reference so that the next Get call can
83
-	// steal it, so we don't have to unmount
84
-	if err := d.DeviceSet.UnmountDevice(id, UnmountFloat); err != nil {
85
-		return err
86
-	}
87 67
 
88 68
 	return nil
89 69
 }
... ...
@@ -96,10 +76,6 @@ func (d *Driver) Remove(id string) error {
96 96
 		return nil
97 97
 	}
98 98
 
99
-	// Sink the float from create in case no Get() call was made
100
-	if err := d.DeviceSet.UnmountDevice(id, UnmountSink); err != nil {
101
-		return err
102
-	}
103 99
 	// This assumes the device has been properly Get/Put:ed and thus is unmounted
104 100
 	if err := d.DeviceSet.DeleteDevice(id); err != nil {
105 101
 		return err
... ...
@@ -115,28 +91,42 @@ func (d *Driver) Remove(id string) error {
115 115
 
116 116
 func (d *Driver) Get(id string) (string, error) {
117 117
 	mp := path.Join(d.home, "mnt", id)
118
-	if err := d.mount(id, mp); err != nil {
118
+
119
+	// Create the target directories if they don't exist
120
+	if err := osMkdirAll(mp, 0755); err != nil && !osIsExist(err) {
119 121
 		return "", err
120 122
 	}
121 123
 
122
-	return path.Join(mp, "rootfs"), nil
123
-}
124
+	// Mount the device
125
+	if err := d.DeviceSet.MountDevice(id, mp, ""); err != nil {
126
+		return "", err
127
+	}
124 128
 
125
-func (d *Driver) Put(id string) {
126
-	if err := d.DeviceSet.UnmountDevice(id, UnmountRegular); err != nil {
127
-		utils.Errorf("Warning: error unmounting device %s: %s\n", id, err)
129
+	rootFs := path.Join(mp, "rootfs")
130
+	if err := osMkdirAll(rootFs, 0755); err != nil && !osIsExist(err) {
131
+		d.DeviceSet.UnmountDevice(id)
132
+		return "", err
128 133
 	}
134
+
135
+	idFile := path.Join(mp, "id")
136
+	if _, err := osStat(idFile); err != nil && osIsNotExist(err) {
137
+		// Create an "id" file with the container/image id in it to help reconscruct this in case
138
+		// of later problems
139
+		if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil {
140
+			d.DeviceSet.UnmountDevice(id)
141
+			return "", err
142
+		}
143
+	}
144
+
145
+	return rootFs, nil
129 146
 }
130 147
 
131
-func (d *Driver) mount(id, mountPoint string) error {
132
-	// Create the target directories if they don't exist
133
-	if err := osMkdirAll(mountPoint, 0755); err != nil && !osIsExist(err) {
134
-		return err
148
+func (d *Driver) Put(id string) {
149
+	if err := d.DeviceSet.UnmountDevice(id); err != nil {
150
+		utils.Errorf("Warning: error unmounting device %s: %s\n", id, err)
135 151
 	}
136
-	// Mount the device
137
-	return d.DeviceSet.MountDevice(id, mountPoint, "")
138 152
 }
139 153
 
140 154
 func (d *Driver) Exists(id string) bool {
141
-	return d.Devices[id] != nil
155
+	return d.DeviceSet.HasDevice(id)
142 156
 }
... ...
@@ -500,15 +500,10 @@ func TestDriverCreate(t *testing.T) {
500 500
 		calls.Assert(t,
501 501
 			"DmTaskCreate",
502 502
 			"DmTaskGetInfo",
503
-			"sysMount",
504 503
 			"DmTaskRun",
505
-			"DmTaskSetTarget",
506 504
 			"DmTaskSetSector",
507
-			"DmTaskSetCookie",
508
-			"DmUdevWait",
509 505
 			"DmTaskSetName",
510 506
 			"DmTaskSetMessage",
511
-			"DmTaskSetAddNode",
512 507
 		)
513 508
 
514 509
 	}()
... ...
@@ -619,15 +614,10 @@ func TestDriverRemove(t *testing.T) {
619 619
 		calls.Assert(t,
620 620
 			"DmTaskCreate",
621 621
 			"DmTaskGetInfo",
622
-			"sysMount",
623 622
 			"DmTaskRun",
624
-			"DmTaskSetTarget",
625 623
 			"DmTaskSetSector",
626
-			"DmTaskSetCookie",
627
-			"DmUdevWait",
628 624
 			"DmTaskSetName",
629 625
 			"DmTaskSetMessage",
630
-			"DmTaskSetAddNode",
631 626
 		)
632 627
 
633 628
 		Mounted = func(mnt string) (bool, error) {
... ...
@@ -650,7 +640,6 @@ func TestDriverRemove(t *testing.T) {
650 650
 			"DmTaskSetTarget",
651 651
 			"DmTaskSetAddNode",
652 652
 			"DmUdevWait",
653
-			"sysUnmount",
654 653
 		)
655 654
 	}()
656 655
 	runtime.GC()