Browse code

devmapper: Store metadata in one file per device

This allows multiple instances of the backend in different containers
to access devices (although generally only one can modify/create them).

Any old metadata is converted on the first run.

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

Alexander Larsson authored on 2014/04/25 06:49:44
Showing 2 changed files
... ...
@@ -106,7 +106,19 @@ func (devices *DeviceSet) loopbackDir() string {
106 106
 	return path.Join(devices.root, "devicemapper")
107 107
 }
108 108
 
109
-func (devices *DeviceSet) jsonFile() string {
109
+func (devices *DeviceSet) metadataDir() string {
110
+	return path.Join(devices.root, "metadata")
111
+}
112
+
113
+func (devices *DeviceSet) metadataFile(info *DevInfo) string {
114
+	file := info.Hash
115
+	if file == "" {
116
+		file = "base"
117
+	}
118
+	return path.Join(devices.metadataDir(), file)
119
+}
120
+
121
+func (devices *DeviceSet) oldMetadataFile() string {
110 122
 	return path.Join(devices.loopbackDir(), "json")
111 123
 }
112 124
 
... ...
@@ -161,14 +173,19 @@ func (devices *DeviceSet) allocateTransactionId() uint64 {
161 161
 	return devices.NewTransactionId
162 162
 }
163 163
 
164
-func (devices *DeviceSet) saveMetadata() error {
165
-	devices.devicesLock.Lock()
166
-	jsonData, err := json.Marshal(devices.MetaData)
167
-	devices.devicesLock.Unlock()
164
+func (devices *DeviceSet) removeMetadata(info *DevInfo) error {
165
+	if err := osRemoveAll(devices.metadataFile(info)); err != nil {
166
+		return fmt.Errorf("Error removing metadata file %s: %s", devices.metadataFile(info), err)
167
+	}
168
+	return nil
169
+}
170
+
171
+func (devices *DeviceSet) saveMetadata(info *DevInfo) error {
172
+	jsonData, err := json.Marshal(info)
168 173
 	if err != nil {
169 174
 		return fmt.Errorf("Error encoding metadata to json: %s", err)
170 175
 	}
171
-	tmpFile, err := ioutil.TempFile(filepath.Dir(devices.jsonFile()), ".json")
176
+	tmpFile, err := ioutil.TempFile(devices.metadataDir(), ".tmp")
172 177
 	if err != nil {
173 178
 		return fmt.Errorf("Error creating metadata file: %s", err)
174 179
 	}
... ...
@@ -186,7 +203,7 @@ func (devices *DeviceSet) saveMetadata() error {
186 186
 	if err := tmpFile.Close(); err != nil {
187 187
 		return fmt.Errorf("Error closing metadata file %s: %s", tmpFile.Name(), err)
188 188
 	}
189
-	if err := osRename(tmpFile.Name(), devices.jsonFile()); err != nil {
189
+	if err := osRename(tmpFile.Name(), devices.metadataFile(info)); err != nil {
190 190
 		return fmt.Errorf("Error committing metadata file %s: %s", tmpFile.Name(), err)
191 191
 	}
192 192
 
... ...
@@ -204,7 +221,12 @@ func (devices *DeviceSet) lookupDevice(hash string) (*DevInfo, error) {
204 204
 	defer devices.devicesLock.Unlock()
205 205
 	info := devices.Devices[hash]
206 206
 	if info == nil {
207
-		return nil, fmt.Errorf("Unknown device %s", hash)
207
+		info = devices.loadMetadata(hash)
208
+		if info == nil {
209
+			return nil, fmt.Errorf("Unknown device %s", hash)
210
+		}
211
+
212
+		devices.Devices[hash] = info
208 213
 	}
209 214
 	return info, nil
210 215
 }
... ...
@@ -224,7 +246,7 @@ func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*Dev
224 224
 	devices.Devices[hash] = info
225 225
 	devices.devicesLock.Unlock()
226 226
 
227
-	if err := devices.saveMetadata(); err != nil {
227
+	if err := devices.saveMetadata(info); err != nil {
228 228
 		// Try to remove unused device
229 229
 		devices.devicesLock.Lock()
230 230
 		delete(devices.Devices, hash)
... ...
@@ -259,9 +281,7 @@ func (devices *DeviceSet) createFilesystem(info *DevInfo) error {
259 259
 	return nil
260 260
 }
261 261
 
262
-func (devices *DeviceSet) loadMetaData() error {
263
-	utils.Debugf("loadMetadata()")
264
-	defer utils.Debugf("loadMetadata END")
262
+func (devices *DeviceSet) initMetaData() error {
265 263
 	_, _, _, params, err := getStatus(devices.getPoolName())
266 264
 	if err != nil {
267 265
 		utils.Debugf("\n--->Err: %s\n", err)
... ...
@@ -274,35 +294,64 @@ func (devices *DeviceSet) loadMetaData() error {
274 274
 	}
275 275
 	devices.NewTransactionId = devices.TransactionId
276 276
 
277
-	jsonData, err := ioutil.ReadFile(devices.jsonFile())
277
+	// Migrate old metadatafile
278
+
279
+	jsonData, err := ioutil.ReadFile(devices.oldMetadataFile())
278 280
 	if err != nil && !osIsNotExist(err) {
279 281
 		utils.Debugf("\n--->Err: %s\n", err)
280 282
 		return err
281 283
 	}
282 284
 
283
-	devices.MetaData.Devices = make(map[string]*DevInfo)
284 285
 	if jsonData != nil {
285
-		if err := json.Unmarshal(jsonData, &devices.MetaData); err != nil {
286
+		m := MetaData{Devices: make(map[string]*DevInfo)}
287
+
288
+		if err := json.Unmarshal(jsonData, &m); err != nil {
286 289
 			utils.Debugf("\n--->Err: %s\n", err)
287 290
 			return err
288 291
 		}
289
-	}
290 292
 
291
-	for hash, d := range devices.Devices {
292
-		d.Hash = hash
293
-		d.devices = devices
293
+		for hash, info := range m.Devices {
294
+			info.Hash = hash
294 295
 
295
-		// If the transaction id is larger than the actual one we lost the device due to some crash
296
-		if d.TransactionId > devices.TransactionId {
297
-			utils.Debugf("Removing lost device %s with id %d", hash, d.TransactionId)
298
-			delete(devices.Devices, hash)
296
+			// If the transaction id is larger than the actual one we lost the device due to some crash
297
+			if info.TransactionId <= devices.TransactionId {
298
+				devices.saveMetadata(info)
299
+			}
300
+		}
301
+		if err := osRename(devices.oldMetadataFile(), devices.oldMetadataFile()+".migrated"); err != nil {
302
+			return err
299 303
 		}
304
+
300 305
 	}
306
+
301 307
 	return nil
302 308
 }
303 309
 
310
+func (devices *DeviceSet) loadMetadata(hash string) *DevInfo {
311
+	info := &DevInfo{Hash: hash, devices: devices}
312
+
313
+	jsonData, err := ioutil.ReadFile(devices.metadataFile(info))
314
+	if err != nil {
315
+		return nil
316
+	}
317
+
318
+	if err := json.Unmarshal(jsonData, &info); err != nil {
319
+		return nil
320
+	}
321
+
322
+	fmt.Printf("Loaded metadata %v\n", info)
323
+
324
+	// If the transaction id is larger than the actual one we lost the device due to some crash
325
+	if info.TransactionId > devices.TransactionId {
326
+		return nil
327
+	}
328
+
329
+	return info
330
+}
331
+
304 332
 func (devices *DeviceSet) setupBaseImage() error {
305 333
 	oldInfo, _ := devices.lookupDevice("")
334
+	utils.Debugf("oldInfo: %p", oldInfo)
306 335
 	if oldInfo != nil && oldInfo.Initialized {
307 336
 		return nil
308 337
 	}
... ...
@@ -349,7 +398,7 @@ func (devices *DeviceSet) setupBaseImage() error {
349 349
 	}
350 350
 
351 351
 	info.Initialized = true
352
-	if err = devices.saveMetadata(); err != nil {
352
+	if err = devices.saveMetadata(info); err != nil {
353 353
 		info.Initialized = false
354 354
 		utils.Debugf("\n--->Err: %s\n", err)
355 355
 		return err
... ...
@@ -457,29 +506,7 @@ func (devices *DeviceSet) ResizePool(size int64) error {
457 457
 func (devices *DeviceSet) initDevmapper(doInit bool) error {
458 458
 	logInit(devices)
459 459
 
460
-	// Make sure the sparse images exist in <root>/devicemapper/data and
461
-	// <root>/devicemapper/metadata
462
-
463
-	hasData := devices.hasImage("data")
464
-	hasMetadata := devices.hasImage("metadata")
465
-
466
-	if !doInit && !hasData {
467
-		return errors.New("Loopback data file not found")
468
-	}
469
-
470
-	if !doInit && !hasMetadata {
471
-		return errors.New("Loopback metadata file not found")
472
-	}
473
-
474
-	createdLoopback := !hasData || !hasMetadata
475
-	data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
476
-	if err != nil {
477
-		utils.Debugf("Error device ensureImage (data): %s\n", err)
478
-		return err
479
-	}
480
-	metadata, err := devices.ensureImage("metadata", DefaultMetaDataLoopbackSize)
481
-	if err != nil {
482
-		utils.Debugf("Error device ensureImage (metadata): %s\n", err)
460
+	if err := osMkdirAll(devices.metadataDir(), 0700); err != nil && !osIsExist(err) {
483 461
 		return err
484 462
 	}
485 463
 
... ...
@@ -512,10 +539,38 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
512 512
 	// so we add this badhack to make sure it closes itself
513 513
 	setCloseOnExec("/dev/mapper/control")
514 514
 
515
+	// Make sure the sparse images exist in <root>/devicemapper/data and
516
+	// <root>/devicemapper/metadata
517
+
518
+	createdLoopback := false
519
+
515 520
 	// If the pool doesn't exist, create it
516 521
 	if info.Exists == 0 {
517 522
 		utils.Debugf("Pool doesn't exist. Creating it.")
518 523
 
524
+		hasData := devices.hasImage("data")
525
+		hasMetadata := devices.hasImage("metadata")
526
+
527
+		if !doInit && !hasData {
528
+			return errors.New("Loopback data file not found")
529
+		}
530
+
531
+		if !doInit && !hasMetadata {
532
+			return errors.New("Loopback metadata file not found")
533
+		}
534
+
535
+		createdLoopback = !hasData || !hasMetadata
536
+		data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
537
+		if err != nil {
538
+			utils.Debugf("Error device ensureImage (data): %s\n", err)
539
+			return err
540
+		}
541
+		metadata, err := devices.ensureImage("metadata", DefaultMetaDataLoopbackSize)
542
+		if err != nil {
543
+			utils.Debugf("Error device ensureImage (metadata): %s\n", err)
544
+			return err
545
+		}
546
+
519 547
 		dataFile, err := attachLoopDevice(data)
520 548
 		if err != nil {
521 549
 			utils.Debugf("\n--->Err: %s\n", err)
... ...
@@ -537,9 +592,9 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
537 537
 	}
538 538
 
539 539
 	// If we didn't just create the data or metadata image, we need to
540
-	// load the metadata from the existing file.
540
+	// load the transaction id and migrate old metadata
541 541
 	if !createdLoopback {
542
-		if err = devices.loadMetaData(); err != nil {
542
+		if err = devices.initMetaData(); err != nil {
543 543
 			utils.Debugf("\n--->Err: %s\n", err)
544 544
 			return err
545 545
 		}
... ...
@@ -608,14 +663,6 @@ func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
608 608
 		}
609 609
 	}
610 610
 
611
-	if info.Initialized {
612
-		info.Initialized = false
613
-		if err := devices.saveMetadata(); err != nil {
614
-			utils.Debugf("Error saving meta data: %s\n", err)
615
-			return err
616
-		}
617
-	}
618
-
619 611
 	if err := deleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil {
620 612
 		utils.Debugf("Error deleting device: %s\n", err)
621 613
 		return err
... ...
@@ -626,11 +673,11 @@ func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
626 626
 	delete(devices.Devices, info.Hash)
627 627
 	devices.devicesLock.Unlock()
628 628
 
629
-	if err := devices.saveMetadata(); err != nil {
629
+	if err := devices.removeMetadata(info); err != nil {
630 630
 		devices.devicesLock.Lock()
631 631
 		devices.Devices[info.Hash] = info
632 632
 		devices.devicesLock.Unlock()
633
-		utils.Debugf("Error saving meta data: %s\n", err)
633
+		utils.Debugf("Error removing meta data: %s\n", err)
634 634
 		return err
635 635
 	}
636 636
 
... ...
@@ -873,7 +920,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) erro
873 873
 	info.mountCount = 1
874 874
 	info.mountPath = path
875 875
 
876
-	return devices.setInitialized(info)
876
+	return nil
877 877
 }
878 878
 
879 879
 func (devices *DeviceSet) UnmountDevice(hash string) error {
... ...
@@ -924,14 +971,6 @@ func (devices *DeviceSet) HasDevice(hash string) bool {
924 924
 	return info != nil
925 925
 }
926 926
 
927
-func (devices *DeviceSet) HasInitializedDevice(hash string) bool {
928
-	devices.Lock()
929
-	defer devices.Unlock()
930
-
931
-	info, _ := devices.lookupDevice(hash)
932
-	return info != nil && info.Initialized
933
-}
934
-
935 927
 func (devices *DeviceSet) HasActivatedDevice(hash string) bool {
936 928
 	info, _ := devices.lookupDevice(hash)
937 929
 	if info == nil {
... ...
@@ -948,17 +987,6 @@ func (devices *DeviceSet) HasActivatedDevice(hash string) bool {
948 948
 	return devinfo != nil && devinfo.Exists != 0
949 949
 }
950 950
 
951
-func (devices *DeviceSet) setInitialized(info *DevInfo) error {
952
-	info.Initialized = true
953
-	if err := devices.saveMetadata(); err != nil {
954
-		info.Initialized = false
955
-		utils.Debugf("\n--->Err: %s\n", err)
956
-		return err
957
-	}
958
-
959
-	return nil
960
-}
961
-
962 951
 func (devices *DeviceSet) List() []string {
963 952
 	devices.Lock()
964 953
 	defer devices.Unlock()
... ...
@@ -820,10 +820,6 @@ func TestGetReturnsValidDevice(t *testing.T) {
820 820
 	if !d.HasActivatedDevice("1") {
821 821
 		t.Fatalf("Expected id 1 to be activated")
822 822
 	}
823
-
824
-	if !d.HasInitializedDevice("1") {
825
-		t.Fatalf("Expected id 1 to be initialized")
826
-	}
827 823
 }
828 824
 
829 825
 func TestDriverGetSize(t *testing.T) {